Web Workers

本文将介绍在 Rsbuild 项目中如何配置和使用 Web Workers

Web Workers

Web Workers 是一种 JavaScript API,它允许网页在后台线程中执行脚本,与主线程(网页)分离。这意味着,你可以使用 Web Workers 来执行计算密集型或长时间运行的任务,而无需阻塞主线程,进而影响网页的性能。

使用 Web Workers

使用 Worker 构造器

Rspack 提供了对 Web Workers 的内置支持,这意味着你不需要任何的 Loader 就可以直接在 Rsbuild 项目中使用 Web Workers。

例如,创建一个名为 worker.js 的文件:

worker.js
self.onmessage = (event) => {
  const result = event.data * 2;
  self.postMessage(result);
};

然后在主线程中使用这个 worker:

index.js
const worker = new Worker(new URL('./worker.js', import.meta.url));

worker.onmessage = (event) => {
  console.log('The results from Workers:', event.data);
};

worker.postMessage(10);

Rspack 默认支持多种 Worker 语法, 查看 Rspack - Web Workers 了解更多。

使用 worker-loader

如果你的项目已经在使用 worker-loader,或者希望使用 worker-loaderinline 等能力,在 Rsbuild 项目中可以使用 worker-loader 的替代方案 worker-rspack-loader

rsbuild.config.ts
export default {
  tools: {
    rspack: {
      resolveLoader: {
        alias: {
          // 修改内联 loader 中 worker-loader 的指向
          // 如 `worker-loader!pdfjs-dist/es5/build/pdf.worker.js`
          'worker-loader': require.resolve('worker-rspack-loader'),
        },
      },
      module: {
        rules: [
          {
            test: /\.worker\.js$/,
            loader: 'worker-rspack-loader',
          },
        ],
      },
    },
  },
};

使用 worker-rspack-loader 时,需要使用 import 来引入 Web Worker 文件,而不是 new Worker('/path/to/worker.js')

import Worker from './file.worker.js';

const worker = new Worker();

worker.postMessage({ a: 1 });

worker-loader 已不再维护,如果你没有内联 Web Workers 的需求,推荐使用 new Worker() 语法。

从远程 URL 加载脚本

默认情况下,worker 脚本会输出成一个独立的 chunk。worker 脚本支持上传到 CDN,但在加载远程脚本时需要遵守同源策略

如果你希望你的 worker 脚本可以跨域访问,常见解法是通过 importScripts (不受 CORS 约束) 加载,可参考如下代码:

index.js
// https://github.com/jantimon/remote-web-worker
import 'remote-web-worker';

const worker = new Worker(new URL('./worker.js', import.meta.url), {
  type: 'classic',
});

worker.onmessage = (event) => {
  console.log('The results from Workers:', event.data);
};

worker.postMessage(10);

关于跨域问题的详细讨论可参考 Discussions - webpack 5 web worker support for CORS?

独立构建

Rsbuild 支持独立构建 Web Workers 产物。当你需要为 Web Workers 配置独立的构建选项,或将 Web Workers 提供给其他应用使用时,可以使用以下方法。

将 Rsbuild 的 output.target 配置项设置为 'web-worker',即可生成运行在 Worker 线程的构建产物。

rsbuild.config.ts
export default {
  output: {
    target: 'web-worker',
  },
};

使用 environments 来同时构建 Web Workers 与主应用:

rsbuild.config.ts
export default {
  environments: {
    web: {
      // 主应用的构建配置
    },
    webWorker: {
      // Web Workers 的构建配置
      output: {
        target: 'web-worker',
      },
    },
  },
};