惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Vercel News
Vercel News
博客园 - 【当耐特】
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
小众软件
小众软件
Hugging Face - Blog
Hugging Face - Blog
aimingoo的专栏
aimingoo的专栏
WordPress大学
WordPress大学
G
Google Developers Blog
博客园 - 叶小钗
大猫的无限游戏
大猫的无限游戏
P
Proofpoint News Feed
J
Java Code Geeks
U
Unit 42
云风的 BLOG
云风的 BLOG
阮一峰的网络日志
阮一峰的网络日志
N
Netflix TechBlog - Medium
宝玉的分享
宝玉的分享
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
D
Docker
V
Visual Studio Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
H
Help Net Security
V
V2EX
T
Tailwind CSS Blog

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
Firefox Extension Manifest V3 vs V2: What Actually Changed
Weather Cloc · 2026-05-04 · via DEV Community

Firefox Extension Manifest V3 vs V2: What Actually Changed

If you've been following Chrome's controversial Manifest V3 migration, you might be wondering: does Firefox have the same MV3? The answer is: yes and no. Firefox has its own implementation of Manifest V3, and it's meaningfully different from Chrome's.

The Short Version

  • Firefox MV3 supports both MV2 and MV3 extensions
  • Firefox's MV3 is less restrictive than Chrome's
  • Firefox still supports browser.webRequest blocking in MV3
  • Service workers replace background pages (same as Chrome)

What Changed: Background Scripts

MV2 (background page):

// manifest.json
{
  "manifest_version": 2,
  "background": {
    "scripts": ["background.js"],
    "persistent": false
  }
}

Enter fullscreen mode Exit fullscreen mode

MV3 (service worker):

// manifest.json
{
  "manifest_version": 3,
  "background": {
    "service_worker": "background.js"
  }
}

Enter fullscreen mode Exit fullscreen mode

The key implication: service workers don't persist state in memory. They're event-driven and can be terminated at any time. Code like this breaks:

// ❌ This DOESN'T work in MV3 service workers
let cachedData = {}; // Lost when service worker terminates!

chrome.tabs.onActivated.addListener(() => {
  if (cachedData.weather) {
    // cachedData might be {} if SW was terminated
  }
});

Enter fullscreen mode Exit fullscreen mode

Fix: Use browser.storage.session (MV3 only) or browser.storage.local:

// ✅ This works in MV3
async function getCachedData() {
  const { cachedData } = await browser.storage.session.get('cachedData');
  return cachedData || {};
}

async function setCachedData(data) {
  await browser.storage.session.set({ cachedData: data });
}

Enter fullscreen mode Exit fullscreen mode

What Changed: Content Security Policy

MV2: More permissive CSP

"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"

Enter fullscreen mode Exit fullscreen mode

MV3: Stricter — no unsafe-eval, no remote scripts

"content_security_policy": {
  "extension_pages": "script-src 'self'; object-src 'self'"
}

Enter fullscreen mode Exit fullscreen mode

This means: no more eval(), no more loading scripts from external CDNs directly. You must bundle all JavaScript.

What Changed: Action API

MV2: Separate browser_action and page_action

MV3: Unified action

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

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

Enter fullscreen mode Exit fullscreen mode

In code:

// MV2
browser.browserAction.setBadgeText({ text: '5' });

// MV3
browser.action.setBadgeText({ text: '5' });

Enter fullscreen mode Exit fullscreen mode

What Firefox Kept (That Chrome Removed)

This is the important difference: Firefox MV3 still allows blocking webRequest.

Chrome replaced blocking webRequest with declarativeNetRequest, which is less powerful but more privacy-preserving. Firefox offers both:

// Firefox MV3 — still works!
browser.webRequest.onBeforeRequest.addListener(
  (details) => {
    if (details.url.includes('tracker.example.com')) {
      return { cancel: true };
    }
  },
  { urls: ['<all_urls>'] },
  ['blocking']
);

Enter fullscreen mode Exit fullscreen mode

This matters for ad blockers and privacy tools — uBlock Origin works on Firefox MV3 because of this.

Migrating a New Tab Extension

For new tab extensions like Weather & Clock Dashboard, the migration is mostly straightforward:

// Before (MV2)
{
  "manifest_version": 2,
  "background": {
    "scripts": ["background.js"],
    "persistent": false
  },
  "browser_action": {},
  "chrome_url_overrides": {
    "newtab": "newtab.html"
  }
}

Enter fullscreen mode Exit fullscreen mode

// After (MV3)
{
  "manifest_version": 3,
  "background": {
    "service_worker": "background.js",
    "type": "module"  // Optional: enables ES modules
  },
  "action": {},
  "chrome_url_overrides": {
    "newtab": "newtab.html"
  }
}

Enter fullscreen mode Exit fullscreen mode

The newtab override itself doesn't change between MV2 and MV3 — that part is stable.

Should You Migrate?

For Firefox: MV2 still works and Mozilla has said they'll support it. Migrating to MV3 is optional for now.

For Chrome: MV2 is being deprecated. If you also publish to the Chrome Web Store, migrating is necessary.

For new extensions: Start with MV3. It's the future-proof choice.


For the Weather & Clock Dashboard, I'm currently on MV2 since the extension is Firefox-only. Migration to MV3 is on the roadmap.

Install the extension: Weather & Clock Dashboard on AMO

Questions about MV3 migration? Drop them in the comments!


Part of a series on building Firefox browser extensions.

firefox #javascript #webdev #browserextension