Skip to main content
把繁重的计算移出页面主线程,避免页面卡住。 Extension.js 按 web 目标的打包器默认行为编译 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 是同源的,两种写法都无需额外设置即可工作:
这是首选路线。让内容脚本保持轻薄,把输入发送给后台 service worker 或 offscreen 文档,让 worker 在那里运行。无可见界面的页面见 Offscreen 文档,往返消息见消息传递

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 会被拒绝,没有办法改变。

后续步骤