知海

Web Workers

webpackjsorg-main指南-教程

Web Workers

从 webpack 5 开始,你可以无需使用 worker-loader 即可使用 Web Workers

语法

js 复制代码
new Worker(new URL("./worker.js", import.meta.url));
js 复制代码
// or customize the chunk name with magic comments
// see https://webpack.js.org/api/module-methods/#magic-comments
new Worker(
  /* webpackChunkName: "foo-worker" */ new URL("./worker.js", import.meta.url),
);

选择该语法是为了允许在没有打包器的情况下运行代码,它在浏览器原生 ECMAScript 模块中同样可用。

注意,虽然 Worker API 表明 Worker 构造函数接受表示脚本 URL 的字符串,但在 webpack 5 中你只能使用 URL

版本要求:5.105.0+

当使用 new Worker() 时,webpack 可以通过包 exports 字段中定义的导出条件名来解析 worker 模块。这允许包自动提供 worker 特定版本的模块。

package.json(位于依赖包中):

json 复制代码
{
  "name": "my-package",
  "exports": {
    ".": {
      "worker": "./index.worker.js",
      "default": "./index.js"
    }
  }
}

当你在 worker 上下文中引入这个包时:

js 复制代码
// Inside a worker file
import { someFunction } from "my-package";

当模块在 worker 上下文中被使用时,webpack 会自动解析到 index.worker.js,无需任何额外配置。

警告: webpack 不支持在 Worker 构造函数中使用变量。例如,以下代码将无法工作:const url = new URL('./path/to/worker.ts', import.meta.url); const worker = new Worker(url);。这是因为 webpack 无法静态地分析该语法。在 webpack 中使用 Worker 语法时,务必了解这一限制。

示例

src/index.js

js 复制代码
const worker = new Worker(new URL("./deep-thought.js", import.meta.url));
worker.postMessage({
  question:
    "The Answer to the Ultimate Question of Life, The Universe, and Everything.",
});
worker.onmessage = ({ data: { answer } }) => {
  console.log(answer);
};

src/deep-thought.js

js 复制代码
globalThis.onmessage = ({ data: { question } }) => {
  self.postMessage({
    answer: 42,
  });
};

从变量设置 public path

当你从变量设置 __webpack_public_path__,且 publicPath 等于 auto 时,worker chunk 将获得独立的运行时,webpack 运行时会自动计算并设置 publicPath,但这很可能并非你期望的结果。

要解决此问题,你需要在 worker 代码内设置 __webpack_public_path__。示例如下:

worker.js

js 复制代码
globalThis.onmessage = ({ data: { publicPath, ...otherData } }) => {
  if (publicPath) {
    __webpack_public_path__ = publicPath;
  }

  // rest of the worker code
};

app.js

js 复制代码
const worker = new Worker(new URL("./worker.js", import.meta.url));

worker.postMessage({ publicPath: globalThis.__MY_GLOBAL_PUBLIC_PATH_VAR__ });

何时使用:

仅当 worker 需要加载额外的 chunk 且资源基础 URL 在运行时确定时(例如,使用 CDN 或多域名部署),才需要使用此模式。

由于 worker 运行在隔离的全局作用域中,自动检测到的 public path 可能与主线程使用的路径不同。在这种情况下,必须显式地将 public path(__webpack_public_path__)传递给 worker,并在 worker 运行时内部进行设置。

注意:这是一个高级用例。如果你的 worker 不加载额外的 chunk,或者你的资源来自静态的同源路径,通常无需手动设置 __webpack_public_path__

Node.js

本节介绍如何通过 worker_threads 模块在 Node.js 环境中使用 Web Workers。

Node.js(>= 12.17.0)也支持类似的语法:

js 复制代码
import { Worker } from "node:worker_threads";

new Worker(new URL("./worker.js", import.meta.url));

注意,这仅在 ESM 中可用。webpack 和 Node.js 都不支持 CommonJS 语法中的 Worker

帮助我们改进文档

发现翻译问题或内容错误?请告诉我们。