如果你还在用 uBlock Origin 的 MV2 版本拦截广告,该做决定了。Google Chrome 已经进入 Manifest V2 扩展支持的最终拆除阶段——不是"逐步过渡",而是彻底封死,包括所有曾经有效的绕过技巧。
为什么这次不同
过去两年,Chrome 对 MV2 的淘汰一直在"温和推进":先是不再接受新的 MV2 扩展提交,然后是逐步在稳定版中弹出迁移提醒。开发者社区也找到了各种绕过方式——修改注册表策略、启用 Developer Mode、使用 Chromium fork 等——让 MV2 扩展继续存活。
但这次的关键信号来自 Chromium 贡献者 Andrey Bershanskiy:他在 w3c WebExtensions Community Group 的 GitHub 仓库中提交了变更,明确指向移除所有绕过机制。这意味着 Chrome 不只是默认禁用 MV2,而是从代码层面确保没有任何开关、策略或 hack 能让 MV2 扩展重新运行。
具体来说,以下绕过手段将全部失效:
| 绕过方式 | 当前状态 | 即将状态 |
|---|---|---|
ExtensionSettings 策略强制允许 MV2 |
有效 | 将被忽略 |
| Developer Mode 挂载 MV2 扩展 | 有效 | 将被阻止 |
--enable-extensions 启动参数 |
有效 | 将被移除 |
| Chromium fork(如 Brave)自行保留 MV2 | 各 fork 自行决定 | 上游代码已删除 |
MV2 到 MV3:核心差异在哪
理解为什么要迁移,先看 MV2 和 MV3 的本质区别:
MV2 的能力模型:扩展拥有持久后台页面(background page),可以长期运行脚本,使用 webRequest API 在请求发出前拦截和修改(blocking webRequest)。这正是 uBlock Origin 高效拦截广告的基础——它在网络层实时过滤每一个请求。
MV3 的限制:
- 后台页面改为 Service Worker,没有持久运行状态,30 秒无活动即休眠
webRequest的 blocking 能力被移除,只能用declarativeNetRequest(DNR)声明式规则- DNR 规则有数量上限(稳定版默认 30,000 条,企业策略可扩展到 150,000)
- 远程代码执行被禁止,不能动态加载脚本
这些限制直接削弱了广告拦截器的实时过滤能力。uBlock Origin 的规则集远超 30,000 条上限,且依赖动态脚本注入处理复杂规则。
检查你的扩展现状
在迁移之前,先搞清楚自己依赖哪些 MV2 扩展。以下是直接可用的检查方法:
# 列出当前 Chrome 安装的所有扩展及其 manifest 版本
# macOS / Linux
find ~/Library/Application\ Support/Google/Chrome/Default/Extensions \
~/.config/google-chrome/Default/Extensions \
-name "manifest.json" -exec sh -c '
dir=$(echo "$1" | sed "s|/manifest.json||")
ver=$(grep -o "\"manifest_version\": [0-9]*" "$1" | grep -o "[0-9]*")
name=$(grep -o "\"name\": \"[^\"]*\"" "$1" | sed "s/\"name\": //;s/\"/"/g")
echo "MV$ver | $name | $dir"
' _ {} \; 2>/dev/null | sort
# Windows (PowerShell)
Get-ChildItem -Path "$env:LOCALAPPDATA\Google\Chrome\User Data\Default\Extensions" `
-Recurse -Filter "manifest.json" | ForEach-Object {
$json = Get-Content $_.FullName | ConvertFrom-Json
"$($json.manifest_version) | $($json.name) | $($_.Directory.FullName)"
} | Sort-Object
运行后你会看到类似输出:
MV2 | uBlock Origin | /Extensions/cjpalhdlnbpafiamejdnhcphjbkeiagm/1.52.0_0
MV3 | uBlock Origin Lite | /Extensions/ddkjphdeanjmkeiigbmdkhojndkbnlba/1.0_0
MV3 | Password Manager | /Extensions/extensionid/2.1_0
标记为 MV2 的扩展就是需要处理的对象。
实际迁移:一个 MV2 扩展的改造示例
假设你有一个简单的 MV2 扩展,功能是拦截特定域名的请求并注入一段样式。以下是完整的迁移过程:
MV2 版本(即将失效):
// manifest.json (MV2)
{
"manifest_version": 2,
"name": "Simple Blocker",
"version": "1.0",
"background": {
"scripts": ["background.js"],
"persistent": true
},
"permissions": [
"webRequest",
"webRequestBlocking",
"<all_urls>"
],
"content_scripts": [
{
"matches": ["*://example.com/*"],
"css": ["hide.css"]
}
]
}
// background.js (MV2) — 实时拦截请求
chrome.webRequest.onBeforeRequest.addListener(
function(details) {
if (details.url.includes("ads.example.com")) {
return { cancel: true };
}
},
{ urls: ["<all_urls>"] },
["blocking"]
);
迁移到 MV3:
// manifest.json (MV3)
{
"manifest_version": 3,
"name": "Simple Blocker",
"version": "2.0",
"background": {
"service_worker": "background.js"
},
"permissions": [
"declarativeNetRequest",
"scripting"
],
"declarative_net_request": {
"rule_resources": [
{
"id": "ad_block_rules",
"enabled": true,
"path": "rules.json"
}
]
},
"host_permissions": [
"*://*/*"
]
}
// rules.json — 声明式拦截规则
[
{
"id": 1,
"priority": 1,
"action": { "type": "block" },
"condition": {
"urlFilter": "||ads.example.com",
"resourceTypes": ["script", "image", "sub_frame", "xmlhttprequest"]
}
},
{
"id": 2,
"priority": 1,
"action": { "type": "block" },
"condition": {
"urlFilter": "*tracking.example.com/pixel*",
"resourceTypes": ["image", "xmlhttprequest"]
}
}
]
// background.js (MV3) — Service Worker,无持久状态
// 动态注入样式(替代 content_scripts 的部分场景)
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
if (changeInfo.status === 'complete' && tab.url?.includes('example.com')) {
chrome.scripting.insertCSS({
target: { tabId: tabId },
css: '.ad-banner { display: none !important; }'
});
}
});
关键改动总结:
webRequest+ blocking →declarativeNetRequest:不再实时拦截,改为预声明规则文件background.scripts+ persistent →service_worker:后台变为事件驱动,无持久页面content_scripts→scriptingAPI:动态注入更灵活,但需要显式调用permissions: <all_urls>→host_permissions:权限声明拆分,运行时授权更细粒度
广告拦截器的现实选择
对于重度依赖 uBlock Origin 的用户,MV3 的 DNR 规则上限是个硬伤。当前可选方案:
- uBlock Origin Lite(MV3 版):由同一作者开发,使用 DNR,但功能受限——无法处理复杂 cosmetic filter,规则数量受上限约束。适合轻度拦截需求。
- AdGuard 浏览器扩展(MV3 版):已迁移到 MV3,支持超过 30,000 条规则(通过多规则集拆分),cosmetic filtering 通过
scriptingAPI 实现。功能比 uBO Lite 更完整。 - 切换到 Firefox:Firefox 仍支持 MV2 的 blocking
webRequest,且承诺不会移除。uBlock Origin 在 Firefox 上功能完整。这是目前最省心的方案。
如果你决定留在 Chrome,可以用以下命令快速安装 AdGuard MV3:
# 直接通过 Chrome Web Store ID 安装(需要 chrome-cli 或手动访问)
# AdGuard MV3 扩展 ID: bgnkhhnnamicmpeenaelnjfhikgbkllg
# macOS 打开扩展页面
open "https://chrome.google.com/webstore/detail/adguard-adblocker/bgnkhhnnamicmpeenaelnjfhikgbkllg"
# 或用命令行检查当前拦截规则数量(AdGuard 安装后)
# 在扩展 Service Worker Console 中执行:
chrome.declarativeNetRequest.getAvailableStaticRuleCount((count) => {
console.log(`剩余可用静态规则槽位: ${count}`);
});
企业环境怎么办
企业 IT 管理员之前依赖 ExtensionSettings 策略强制保留 MV2 扩展。这条路即将封死。当前可做的准备:
// Windows: 注册表策略路径
// HKLM\Software\Policies\Google\Chrome\ExtensionSettings
// 或 HKLM\Software\Policies\BraveSoftware\Brave\ExtensionSettings
// 策略 JSON 示例(注意:force_installed 对 MV2 即将失效)
{
"cjpalhdlnbpafiamejdnhcphjbkeiagm": {
"installation_mode": "force_installed",
"update_url": "https://clients2.google.com/service/update2/crx"
},
"*": {
"installation_mode": "blocked"
}
}
// 应迁移为允许 MV3 替代扩展
{
"ddkjphdeanjmkeiigbmdkhojndkbnlba": {
"installation_mode": "force_installed",
"update_url": "https://clients2.google.com/service/update2/crx"
},
"bgnkhhnnamicmpeenaelnjfhikgbkllg": {
"installation_mode": "allowed"
},
"*": {
"installation_mode": "blocked"
}
}
# 检查当前 Chrome 策略是否生效
# macOS
defaults read com.google.Chrome ExtensionSettings 2>/dev/null | python3 -m json.tool
# Windows
reg query "HKLM\Software\Policies\Google\Chrome" /v ExtensionSettings 2>nul
迁移检查清单
在 MV2 彻底失效之前,完成以下步骤:
- [ ] 运行扩展扫描脚本,列出所有 MV2 扩展
- [ ] 为每个 MV2 扩展确认是否有 MV3 替代版本(Web Store 搜索或联系开发者)
- [ ] 广告拦截器:评估 uBO Lite / AdGuard MV3 / Firefox 三条路
- [ ] 自研扩展:将
webRequest blocking改写为declarativeNetRequest规则文件 - [ ] 自研扩展:将
background.page/scripts改为service_worker,处理休眠逻辑 - [ ] 自研扩展:将远程代码加载改为本地打包(MV3 禁止远程脚本)
- [ ] 企业环境:更新
ExtensionSettings策略,指向 MV3 扩展 ID - [ ] 测试:在 Chrome Canary 中验证所有扩展正常工作(Canary 最先执行新政策)
这次不是"建议迁移",是"强制断电"。提前准备比事后补救成本低得多。