从MV2迁移至MV3:webRequest转DeclarativeNetRequest的实现疑问
解决方案:MV3 替代 MV2 webRequest 实现需求
一、监听请求完成/错误事件
MV3 中仍保留了 chrome.webRequest.onCompleted 和 chrome.webRequest.onErrorOccurred 事件,无需切换到 DeclarativeNetRequest(DNR),只需调整 manifest 权限和代码运行环境:
1. 更新 manifest.json 权限
添加 webRequest 权限和主机权限:
{ "manifest_version": 3, "permissions": ["webRequest"], "host_permissions": ["<all_urls>"] }
2. 迁移原有监听逻辑
将代码放到 service worker(MV3 替代后台页面的文件)中,直接复用原有逻辑:
// service-worker.js function webCompleteOrError(details) { // 保留你原有的处理逻辑,比如打印请求状态、错误信息等 console.log('请求详情:', details.url, details.statusCode || details.error); } // 注册监听事件 chrome.webRequest.onCompleted.addListener(webCompleteOrError, { urls: ["http://*/*", "https://*/*"] }); chrome.webRequest.onErrorOccurred.addListener(webCompleteOrError, { urls: ["http://*/*", "https://*/*"] });
二、移除指定响应头(推荐用 DeclarativeNetRequest)
MV3 推荐用 DNR 替代阻塞式的 webRequest 头修改,性能更优且无需 webRequestBlocking 权限,实现步骤如下:
1. 声明 DNR 权限
在 manifest.json 中配置相关权限和规则文件:
{ "manifest_version": 3, "permissions": ["declarativeNetRequest"], "host_permissions": ["<all_urls>"], "declarative_net_request": { "rule_resources": [{ "id": "header_rules", "enabled": true, "path": "rules.json" }] } }
2. 创建静态规则文件 rules.json
通过规则直接匹配目标请求并移除指定响应头:
[ { "id": 1, "priority": 1, "action": { "type": "modifyHeaders", "responseHeaders": [ { "header": "X-Frame-Options", "operation": "remove" }, { "header": "Frame-Options", "operation": "remove" }, { "header": "Content-Security-Policy", "operation": "remove" } ] }, "condition": { "urlFilter": "*", "resourceTypes": ["main_frame", "sub_frame"], "tabIds": ["YOUR_TAB_ID"] // 替换为你的目标 tabId,动态场景见下文 } } ]
动态调整规则(适配 tabId 变化场景)
如果 global_pinger_value 是动态更新的,可通过代码动态添加/修改规则:
// service-worker.js async function updateHeaderRules(targetTabId) { // 先清除旧规则 await chrome.declarativeNetRequest.updateDynamicRules({ removeRuleIds: [1] }); // 添加新规则 await chrome.declarativeNetRequest.updateDynamicRules({ addRules: [{ "id": 1, "priority": 1, "action": { "type": "modifyHeaders", "responseHeaders": [ { "header": "X-Frame-Options", "operation": "remove" }, { "header": "Frame-Options", "operation": "remove" }, { "header": "Content-Security-Policy", "operation": "remove" } ] }, "condition": { "urlFilter": "*", "resourceTypes": ["main_frame", "sub_frame"], "tabIds": [targetTabId] } }] }); } // 示例:通过消息触发规则更新 chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { if (message.type === 'updateTargetTab') { updateHeaderRules(message.tabId); sendResponse({ success: true }); } });
备选:继续使用 webRequest 阻塞方式(不推荐)
若坚持用原有 webRequest 逻辑,需声明 webRequestBlocking 权限:
{ "manifest_version": 3, "permissions": ["webRequest", "webRequestBlocking"], "host_permissions": ["<all_urls>"] }
迁移后的 handleHeaders 函数(放到 service worker 中):
// service-worker.js let global_pinger_value = 0; // 你的全局 tabId 变量 function handleHeaders(details) { if (details.tabId !== global_pinger_value && details.tabId !== -1) { return { responseHeaders: details.responseHeaders }; } // 过滤移除指定头 details.responseHeaders = details.responseHeaders.filter(header => { const lowerName = header.name.toLowerCase(); return !['x-frame-options', 'frame-options', 'content-security-policy'].includes(lowerName); }); return { responseHeaders: details.responseHeaders }; } chrome.webRequest.onHeadersReceived.addListener( handleHeaders, { urls: ['<all_urls>'], types: ['sub_frame', 'main_frame'] }, ['blocking', 'responseHeaders'] );
关键注意事项
- MV3 后台逻辑必须放在 service worker 中,代码需适配事件驱动模型,全局变量无法持久化(可改用
chrome.storage.local存储)。 - DeclarativeNetRequest 是 MV3 官方推荐方案,无请求阻塞风险,优先使用。
- 主机权限需明确声明,MV3 不再支持模糊的权限写法,推荐用
<all_urls>或具体域名。
内容的提问来源于stack exchange,提问作者Nikola Oravec
相关产品推荐
相关产品推荐

