declarativeNetRequest API 构建一个 adblocker(也写作 ad blocker 或 content blocker)。你声明匹配规则,浏览器在请求离开网络栈之前原生地拦截它们。
你要构建什么
为什么 MV3 用它取代了阻塞式 webRequest
Manifest V2 的广告拦截器注册阻塞式webRequest 监听器。每个请求都要暂停,等扩展的 JavaScript 决定它的去留。出于性能和隐私考虑,Manifest V3 移除了这种模型。使用 declarativeNetRequest 时,浏览器自己求值你的规则。你的代码从不站在请求路径上,也从不为了拦截而读取请求内容。
对于代理类的用例,比如把所有流量路由到另一台服务器,请改用 proxy API 而不是请求规则。
Manifest
拦截和放行规则不需要 host 权限。重定向规则和 header 规则需要受影响站点的 host 权限。manifest.json
rule_resources 引用的规则集文件,并把它随构建输出一起生成。
静态规则
静态规则放在rules.json 中,随扩展加载而加载。
rules.json
||domain^ 过滤器语法匹配一个域名及其全部子域名。
拦截整个页面
在resourceTypes 里写上 main_frame 的规则会拦截顶层导航,而不只是子资源:
rules.json
- Chrome 会把标签页替换成它自己的拦截页,显示 “This page has been blocked by an extension” 和代码
ERR_BLOCKED_BY_CLIENT。控制台里没有任何输出。 - Firefox 会取消这次导航,标签页保留之前的页面。没有错误页,也没有控制台条目。
dist/<browser>/declarative_net_request/ 并改写 manifest 里的路径,所以按上面 manifest 的写法引用它即可。
本节和下一节的行为是在 Chrome 155 与 Firefox 158 上、使用 Extension.js 4.1.33 测得的。
把被拦截的页面重定向到扩展内的页面
把block 动作换成 redirect,指向随扩展一起发布的页面:
rules.json
public/blocked.html。Extension.js 会把 public/ 复制到输出根目录,所以 /blocked.html 无需在 manifest 里登记就能解析。
重定向需要的权限比拦截多,而且两个浏览器不一样:
- Chrome 需要覆盖该站点的主机权限。没有它,规则就是静默的空操作:页面正常加载,规则集仍显示已启用,控制台里什么都没有。对于指向扩展页面的
main_frame重定向,Chrome 不需要web_accessible_resources。 - Firefox 既需要主机权限,也需要把页面列进
web_accessible_resources。缺少web_accessible_resources条目时,导航会以NS_ERROR_DOM_BAD_URI失败,标签页停留在原处。缺少主机权限时则和 Chrome 一样是静默的空操作。
action 模板把 Firefox 构建为 Manifest V2,那里的主机权限写在 permissions 中,web_accessible_resources 是字符串列表。带前缀的键会在其目标上替换掉同名的普通键,所以 Firefox 的列表要再写一次 declarativeNetRequest。借助浏览器专属字段,一份 manifest 同时覆盖两个浏览器:
manifest.json
firefox: 键,在普通的 web_accessible_resources 下使用对象形式 [{ "resources": ["blocked.html"], "matches": ["<all_urls>"] }]。两个浏览器都接受。
动态规则
把动态规则用于运行时会变化的过滤器,比如用户手动添加的拦截清单条目。重新添加之前先移除对应的规则 id,让更新保持幂等。background.js
declarativeNetRequest 参考文档中确认当前的限制。
在徽章上统计被拦截的请求
一次调用就能把 action 徽章变成每个标签页的规则匹配计数器。background.js
getMatchedRules 自己读取匹配到的规则,请添加 declarativeNetRequestFeedback 权限。
运行
在编辑manifest.json 之前,请注意 manifest 变更需要重启开发服务器。见开发期更新行为。
Firefox 说明
- Firefox 在 Manifest V3 中支持
declarativeNetRequest。 - Firefox 不支持
setExtensionActionOptions,所以徽章计数器只在 Chromium 上可用。 - Firefox 在 Manifest V3 中仍然允许阻塞式
webRequest,而 Chrome 把它保留给策略安装的扩展。 - 当两个目标出现分歧时,使用浏览器特定的 manifest 字段。
从模板开始
action 模板自带一个后台脚本和一个工具栏 popup,是拦截器 UI 的好起点。
最佳实践
- 静态规则放在
rules.json里,动态规则留给用户的选择。 - 给每条动态规则一个稳定的 id,让移除保持可预期。
- 把
resourceTypes收窄到你实际拦截的类型,而不是所有类型。 - 优先使用拦截和放行规则,它们不需要 host 权限。
- 发布过滤器更新之前,先在真实页面上测试规则。
下一步
- 在拦截网络请求中观察流量而不拦截它。
- 用安全检查清单审查你的权限面。
- 回顾 Manifest V3 概念了解后台模型。

