VOOZH about

URL: https://dev.to/weatherclockdash/firefox-extension-manifest-v3-migration-what-actually-changed-46gk

⇱ Firefox Extension Manifest V3 Migration: What Actually Changed - DEV Community


Firefox Extension Manifest V3 Migration: What Actually Changed

Manifest V3 (MV3) has been a contentious topic in browser extension development — mostly because of Chrome's aggressive changes to blocking WebRequest API. Firefox's approach is different and more developer-friendly. Here's what actually changed and what you need to know.

The Short Version for Firefox

Firefox's MV3 implementation is more permissive than Chrome's:

  • Blocking WebRequest still works (unlike Chrome, which deprecated it)
  • Background pages → service workers (same as Chrome)
  • Browser action → new unified action key
  • browser_action / page_action → deprecated, use action

What Actually Changed in manifest.json

Version declaration

//MV2{"manifest_version":2}//MV3{"manifest_version":3}

Action key

//MV2{"browser_action":{"default_popup":"popup.html","default_icon":"icon.png"}}//MV3{"action":{"default_popup":"popup.html","default_icon":"icon.png"}}

Background scripts → service workers

//MV2{"background":{"scripts":["background.js"]}}//MV3{"background":{"service_worker":"background.js"}}

Host permissions moved out of permissions

//MV2{"permissions":["https://api.example.com/*","storage","tabs"]}//MV3{"permissions":["storage","tabs"],"host_permissions":["https://api.example.com/*"]}

Service Worker Gotchas

The biggest behavioral change is background scripts becoming service workers. Service workers:

  1. Don't have access to the DOM
  2. Get terminated when idle (no persistent state in memory)
  3. Must use self instead of window
// MV2 background script — this works
window.myGlobalState = {};
setInterval(() => console.log('still alive'), 1000);

// MV3 service worker — this breaks
// window is not defined in service worker scope
// State is lost when the service worker stops

// Instead, persist state to storage
self.addEventListener('message', async (event) => {
 const { type, data } = event.data;
 if (type === 'SAVE_STATE') {
 await browser.storage.session.set({ state: data });
 }
});

Keeping a service worker alive

For new tab extensions, this is less of an issue since the new tab page itself is a foreground page with a normal DOM context. But if you need the background script:

// Use alarms to keep the service worker alive
browser.alarms.create('keepAlive', { periodInMinutes: 0.4 });
browser.alarms.onAlarm.addListener((alarm) => {
 if (alarm.name === 'keepAlive') {
 // Service worker is alive
 }
});

Content Security Policy Changes

MV3 tightened CSP:

//MV2thiswasallowed{"content_security_policy":"script-src 'self' 'unsafe-eval'; object-src 'self'"}//MV3unsafe-evalisNOTallowedinextensionpages{"content_security_policy":{"extension_pages":"script-src 'self'; object-src 'self'"}}

This breaks libraries that use eval() — notably some templating engines and older versions of Angular.

What Stayed the Same

For simple extensions like new tab pages, most things don't change:

  • chrome_url_overrides (or browser_url_overrides) still works
  • browser.storage API unchanged
  • browser.tabs API unchanged
  • Content scripts work the same way
  • The extension popup works the same way

Real-World Migration Example

Here's the before/after for Weather & Clock Dashboard:

//Before(MV2){"manifest_version":2,"browser_action":{},"permissions":["storage"]}//After(MV3){"manifest_version":3,"action":{},"permissions":["storage"]}

For this extension (pure new tab page, no background script, no remote code), the migration was literally two line changes.

Should You Migrate?

For Firefox extensions published to AMO:

  • MV3 is not yet required — AMO still accepts MV2
  • MV3 is recommended for new extensions
  • Chrome requires MV3 if you want to publish there

If you're building Firefox-only and it's working on MV2, there's no urgent need to migrate. But MV3 is the future, and Firefox's implementation is sane — so for new extensions, start with MV3.

Key Takeaways

  1. Firefox MV3 keeps blocking WebRequest — huge win vs Chrome
  2. Background → service worker is the biggest behavioral change
  3. For new tab extensions, migration is usually 2-3 line changes
  4. CSP is stricter — watch out for eval() usage in dependencies
  5. Host permissions are now separate from other permissions

Weather & Clock Dashboard is a free Firefox extension built with MV3 — live weather, world clocks, search bar. No tracking, MIT licensed.