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
actionkey -
browser_action/page_action→ deprecated, useaction
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:
- Don't have access to the DOM
- Get terminated when idle (no persistent state in memory)
-
Must use
selfinstead ofwindow
// 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:
//MV2—thiswasallowed{"content_security_policy":"script-src 'self' 'unsafe-eval'; object-src 'self'"}//MV3—unsafe-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(orbrowser_url_overrides) still works -
browser.storageAPI unchanged -
browser.tabsAPI 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
- Firefox MV3 keeps blocking WebRequest — huge win vs Chrome
- Background → service worker is the biggest behavioral change
- For new tab extensions, migration is usually 2-3 line changes
- CSP is stricter — watch out for
eval()usage in dependencies - 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.
For further actions, you may consider blocking this person and/or reporting abuse
