匹配规则 match_patterns
本教程共 56 篇 · 第 17 篇 · 更新于 2026-08-13 · 约 8 分钟阅读
本节目标:学完你能准确写出任意范围的匹配模式,知道通配符能放哪不能放哪,也能一眼看出一条模式为什么非法或为什么匹配不上。
匹配模式(match patterns)是一串带通配符的网址,用来描述”一组网址”。内容脚本靠它决定注入哪些页面,宿主权限靠它决定放行哪些站点。这是整个扩展平台里出现频率最高的一种语法,写错一个字符,扩展可能直接加载失败。
17-1 四段结构
一条匹配模式的完整结构是这样的:
<scheme>://<host>:<port>/<path>
其中端口是可选的,其余三段都得有。路径段不能缺省,但允许”带尾斜杠的空路径”——https://*/ 合法,https://example.com(没有斜杠)非法。这四段各有各的规则,我们一段一段拆。
先记一个总原则:匹配模式不是正则,也不是 glob。它只支持 * 这一个通配符,而且 * 出现在哪一段、放在什么位置,规则都不同。别拿正则的直觉去猜。
17-2 scheme:只有四种写法
协议部分必须是下面这几种之一,后面跟冒号加双斜杠:
| 写法 | 匹配范围 |
|---|---|
http | 只匹配 http |
https | 只匹配 https |
* | 只匹配 http 和 https |
file | 匹配本地文件网址 |
最容易被误解的是 *。很多人以为它是”所有协议”,其实它只覆盖 http 和 https 两个。你想匹配本地文件,必须显式写 file。
还有一类协议根本不能写在模式里,比如 about:、data:。想让脚本进入这类框架,得靠 content_scripts 的 match_origin_as_fallback 字段,不是靠改协议段。
17-3 host:通配符只能放开头
主机部分有三种合法形式:
- 完整主机名,比如
www.example.com,只匹配这一个主机。 *.加主机名,比如*.example.com,匹配 example.com 以及它的所有子域。- 单独一个
*,匹配任意主机。
规则的关键约束只有一句:如果用了通配符,它必须是第一个字符或唯一字符,并且后面紧跟一个点(.)或斜杠(/)。
按这条规则倒推,下面这些写法全是非法的:
example.*.com—— 通配符不在开头。*example.com—— 通配符后面不是点或斜杠。www.*—— 同上。
还有一个 Chromium 平台的明确限制:不支持顶级域名通配。也就是说 http://google.*/* 这种”匹配 google 所有国家域名”的写法不存在,你只能一个个列出来:
{
"matches": [
"http://google.es/*",
"http://google.fr/*"
]
}
Note
*.example.com是包含 example.com 本身的,不用再单独补一条example.com。这点和某些 DNS 通配的语义不同,别多写。
17-4 port 与 path
端口段是可选的。不写的时候,等价于写了 :*,也就是匹配所有端口。所以 http://localhost/* 会匹配 localhost 上的任意端口,本地开发调试时很方便。反过来,如果你显式写了端口,就只匹配那个端口。
路径段必须存在,不能省(https://*/ 这种带尾斜杠的空路径算合法,https://example.com 不带斜杠则非法)。约定俗成的写法是 /*,表示任意路径。有两个细节值得记:
- 在
host_permissions里,路径同样必须写,但它的值会被忽略。所以那儿一律写/*就好。 - 网址里的
#片段在匹配之前就被去掉了。所以模式里带片段的写法,比如https://example.com/#section1,永远匹配不上。
路径匹配还会把查询字符串算进去,这点很容易翻车。比如模式 https://*/path 能匹配 https://example.com/path,但匹配不上 https://example.com/path?foo=1——因为查询字符串让实际路径不再等于 path 了。想连带查询字符串一起匹配,末尾用 /* 或 *。
Tip我建议你养成习惯:路径段除了极特殊需求,一律写
/*。想收窄范围优先靠 host 段和exclude_matches,而不是在路径上抠字符,那样最容易漏匹配。
17-5 合法示例照着抄
下面这几条是官方给的示例模式,覆盖了日常九成需求:
| 模式 | 含义 |
|---|---|
https://*/* | 任意主机的所有 https 页面 |
https://*/foo* | 任意主机、路径以 foo 开头的 https 页面 |
https://*.google.com/foo*bar | google.com 及其子域、路径以 foo 开头且以 bar 结尾 |
file:///foo* | 路径以 foo 开头的本地文件 |
http://127.0.0.1/* | 主机为 127.0.0.1 的所有 http 页面 |
http://localhost/* | localhost 的任意端口 |
*://mail.google.com/* | mail.google.com 的 http 与 https 页面 |
注意 https://*.google.com/foo*bar 这条,路径中间也能放通配符,https://docs.google.com/foobar 和 https://www.google.com/foo/baz/bar 都会命中。
17-6 非法写法对照表
写错的模式不会”静默不匹配”,而是会让扩展加载报错。这张表按出错原因整理,对照着自查:
| 模式 | 问题 | 原因 |
|---|---|---|
resource://path/ | 非法 | 协议不在支持列表里 |
https://example.com | 非法 | 缺少路径段 |
https://example.*.com/ | 非法 | host 里的通配符不在开头 |
https://*example.com/ | 非法 | 通配符后面不是 . 或 / |
http*://example.com/ | 非法 | 协议段的通配符不能和字母混写 |
*://* | 非法 | 路径为空,应写成 *://*/* |
file://* | content_scripts 中非法 | 路径为空,应写成 file:///*;但它在 host_permissions 里会被 Chrome 自动纠正为 file:///*(合法) |
https://example.com/#section1 | 匹配不上 | 片段在匹配前已被移除 |
最后两行值得单独盯一下。file:// 后面是三个斜杠,因为主机段为空,第三个斜杠属于路径。写成两个斜杠是最常见的手误之一。
17-7 <all_urls> 与本地文件的特殊约定
有两个特殊写法不符合上面的四段结构,单独记。
"<all_urls>" 匹配所有以受支持协议开头的网址,等于把合法模式全包了。它写起来最省事,代价也最直接:因为影响所有主机,用了它的扩展在应用商店的审核时间可能会更长。我建议你只在确实需要全网生效时才用。
"file:///*" 让扩展能在本地文件上运行。这个权限比较特殊——即使你在清单里声明了,也需要用户在扩展详情页里手动勾选”允许访问文件网址”才生效。装上就能用是不成立的,功能依赖本地文件的扩展一定要在界面上提示用户去开这个开关。
17-8 同一套语法,很多地方复用
匹配模式不是内容脚本专属的,学一次多处受益。它至少出现在这几个位置:
content_scripts的matches与exclude_matches:决定注入哪些页面。host_permissions:申请对哪些站点的宿主权限(路径写了会被忽略)。web_accessible_resources的matches:决定哪些站点能加载你的扩展资源。externally_connectable的matches:决定哪些页面能给扩展发消息。
{
"manifest_version": 3,
"host_permissions": ["https://api.example.com/*"],
"content_scripts": [
{
"matches": ["https://*.example.com/*"],
"exclude_matches": ["https://admin.example.com/*"],
"js": ["content-script.js"]
}
]
}
这段声明的意思是:脚本注入到 example.com 所有子域,但把后台管理子域排除掉;另外单独申请对 api.example.com 的宿主权限,供跨域请求使用。
17-9 写窄一点的三个理由
新手图省事爱写 <all_urls>,我不建议。收窄范围有三个实际好处:
- 用户安装时看到的权限提示更温和,愿意装的人更多。
- 商店审核更快,被质疑的概率更低。
- 脚本不会在无关页面上白跑,页面性能和你的调试体验都更好。
具体做法上,先精确到域名,再用 exclude_matches 剔掉后台、登录、支付这类不该动的页面。改完记得实测:打开一个应该命中的页面和一个不该命中的页面,各看一眼脚本有没有跑。匹配模式这东西凭想象很容易出错,实测两分钟就能定性。
17-10 小结
匹配模式是 <scheme>://<host>:<port>/<path> 四段结构,端口可选,路径必填。协议段的 * 只覆盖 http 和 https;主机段的通配符必须在开头且后跟点或斜杠,且不支持顶级域名通配;路径段习惯写 /*,片段不参与匹配,查询字符串会算进路径。<all_urls> 和 file:/// 是两个特殊约定,前者拖慢审核,后者要用户手动授权。
下一章我们把 run_at 和 world 两个字段讲透——同样是内容脚本的配置,一个决定”什么时候进场”,一个决定”进场后站在哪个世界”。