new Worker(new URL("./worker.js", import.meta.url))。这个调用会在 dist/<browser>/ 根目录产出一个独立的 worker 块,编译后的调用通过 chrome.runtime.getURL() 指向该块。这部分是正常的。
拒绝发生在浏览器一侧。worker 脚本必须与创建它的文档同源。内容脚本背后的文档是宿主页面,所以下面两种写法都会失败。
内容脚本实际得到的结果
下面这段内容脚本能正常编译,运行时失败:https://example.com 上,Chromium 报告:
web_accessible_resources 也解除不了这个限制。它控制的是页面能否加载该文件,而不是该文件能否成为外部源的 worker。
以上是在 Chromium
上、用运行于公开页面的内容脚本实测的结果。Firefox 和 Safari
没有实测,因此请把上面的报错视为 Chromium 的行为。
在扩展自己的页面里运行 worker
popup、选项页、侧边栏和 offscreen 文档都从chrome-extension:// 源加载。在那里创建的 worker 是同源的,两种写法都无需额外设置即可工作:
blob 变通方案及其两个前提
当这项工作必须留在页面里时,请取回 worker 源码,并用 blob URL 构造 worker。blob 继承页面的源,因此浏览器会接受:extension build 不会把 worker 块加入 web_accessible_resources,所以请自己在 manifest.json 中声明该文件:
fetch 会以 TypeError: Failed to fetch 失败,请求显示为 chrome-extension://invalid/。
宿主页面的 CSP 必须允许 blob worker。 发送 worker-src 'self' 的页面会拦截该 blob,而且失败是静默的。构造函数正常返回,随后 worker 通过 onerror 失败,消息为空:
new Worker 外面的 try/catch 完全捕获不到它。请挂上 onerror 处理器,并把它当作真正的失败信号。
三种做法的取舍
- 扩展页面不需要任何设置,两种写法都可用。
- 内容脚本加 blob 需要一条清单条目,以及宽松的页面 CSP。
- 内容脚本直接用扩展 URL 会被拒绝,没有办法改变。
后续步骤
- 阅读 Offscreen 文档,了解无可见页面的后台工作。
- 阅读可被网页访问的资源,了解清单条目。
- 阅读内容脚本,了解页面源还限制了什么。

