本文将介绍在 Rsbuild 项目中如何配置和使用 Web Workers。
Web Workers 是一种 JavaScript API,它允许网页在后台线程中执行脚本,与主线程(网页)分离。这意味着,你可以使用 Web Workers 来执行计算密集型或长时间运行的任务,而无需阻塞主线程,进而影响网页的性能。
Rspack 提供了对 Web Workers 的内置支持,这意味着你不需要任何的 Loader 就可以直接在 Rsbuild 项目中使用 Web Workers。
例如,创建一个名为 worker.js 的文件:
self.onmessage = (event) => { const result = event.data * 2; self.postMessage(result); };然后在主线程中使用这个 worker:
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 的 inline 等能力,在 Rsbuild 项目中可以使用 worker-loader 的替代方案 worker-rspack-loader。
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()语法。
默认情况下,worker 脚本会输出成一个独立的 chunk。worker 脚本支持上传到 CDN,但在加载远程脚本时需要遵守同源策略。
如果你希望你的 worker 脚本可以跨域访问,常见解法是通过 importScripts (不受 CORS 约束) 加载,可参考如下代码:
// 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?
当你的应用中既包含主线程代码,也包含通过 new Worker 创建的 Web Worker 时,需要注意:由于 Web Worker 运行在独立的线程中,与主线程环境隔离,Rsbuild 提供的 polyfill entry 方案 无法在 Web Worker 中生效。此时,建议改用 usage 方案,为 Web Worker 单独注入所需的 polyfill 代码。
export default { output: { polyfill: 'usage', }, };Rsbuild 支持独立构建 Web Workers 产物。当你需要为 Web Workers 配置独立的构建选项,或将 Web Workers 提供给其他应用使用时,可以使用以下方法。
将 Rsbuild 的 output.target 配置项设置为 'web-worker',即可生成运行在 Worker 线程的构建产物。
export default { output: { target: 'web-worker', }, };使用 environments 来同时构建 Web Workers 与主应用:
export default { environments: { web: { // 主应用的构建配置 }, webWorker: { // Web Workers 的构建配置 output: { target: 'web-worker', }, }, }, };