使用 Web Workers

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

Web Workers

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

使用 Web Workers

使用 Worker 构造器

Web Workers 是 Rspack 的一等公民,这意味着你不需要任何的 Loader 就可以直接在 Rspack / Rsbuild 项目中使用 Web Workers。详情可参考 Rspack - Web Workers

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

worker.js

  1. self.onmessage = (event) => {
  2. const result = event.data * 2;
  3. self.postMessage(result);
  4. };

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

index.js

  1. const worker = new Worker(new URL('./worker.js', import.meta.url));
  2. worker.onmessage = (event) => {
  3. console.log('The results from Workers:', event.data);
  4. };
  5. worker.postMessage(10);

使用 worker-loader

worker-loader 已不再维护,推荐使用 new Worker() 语法。

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

  1. export default {
  2. tools: {
  3. rspack: {
  4. resolveLoader: {
  5. alias: {
  6. // 修改内联 loader 中 worker-loader 的指向,如 `worker-loader!pdfjs-dist/es5/build/pdf.worker.js`
  7. 'worker-loader': require.resolve('worker-rspack-loader'),
  8. },
  9. },
  10. module: {
  11. rules: [
  12. {
  13. test: /\.worker\.js$/,
  14. loader: 'worker-rspack-loader',
  15. },
  16. ],
  17. },
  18. },
  19. },
  20. };

从远程 URL 加载脚本(跨域)

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

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

index.js

  1. 1// https://github.com/jantimon/remote-web-worker
  2. 2import 'remote-web-worker';
  3. 3
  4. 4const worker = new Worker(new URL('./worker.js', import.meta.url), {
  5. 5 type: 'classic',
  6. 6});
  7. 7
  8. 8worker.onmessage = (event) => {
  9. 9 console.log('The results from Workers:', event.data);
  10. 10};
  11. 11
  12. 12worker.postMessage(10);

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

构建 Web Workers 产物

Rsbuild 支持独立构建 Web Workers 产物,这在你需要将 Web Workers 产物提供给其他应用使用时很有帮助。

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

  1. export default {
  2. output: {
  3. target: 'web-worker',
  4. },
  5. };