CC 4.0 协议
本节内容派生于以下链接指向的内容 ,并遵守 CC BY 4.0 许可证的规定。
以下内容如果没有特殊声明,可以认为都是基于原内容的修改和删减后的结果。
Web Workers
Rspack 提供了对 Web Workers 的内置支持,这意味着你不需要任何的 Loader 就可以直接使用 Web Workers。
使用方式
基本的 Worker 创建语法:
通过 name 属性可以自定义 Worker 的 chunk 名称(需要属性值可被静态分析),此名称会替换生成的 chunk 文件名中的 [name] 占位符:
选择该语法的原因在于其具备良好的标准兼容性,它基于标准的 ECMAScript 模块规范,即使在没有构建工具的环境中也能正常运行。例如,它可以直接在支持 ES modules 的现代浏览器中执行。
使用示例可参考:
限制
-
由于 Rspack 依赖静态分析来识别 worker 的使用,因此它有以下两个限制:
-
new Worker以及其他类似 worker 的 API 通常也可以接受 URL 的字符串表示,但 Rspack 只支持传入 URL 对象。实际使用中,你必须传入new URL('./worker.js', import.meta.url)。 -
Rspack 无法静态分析
new Worker中使用的变量。例如,以下代码将不起作用:
-
-
/* webpackEntryOptions: { filename: "workers/[name].js" } */魔法注释目前仍不支持。
内置语法
除 new Worker() 以外,Rspack 还默认支持以下内置形式:
new SharedWorker(),详见 SharedWorker。
import { Worker } from "worker_threads":常用于 Node.js 环境,详见 Worker threads。
navigator.serviceWorker.register():用于注册 Service Worker,详见 ServiceWorkerContainer。
自定义语法
可以通过 module.parser.javascript.worker 告诉 Rspack 哪些表达式要按 Worker 类入口语法处理:
true保留内置默认值,等价于['...']。false关闭 worker 语法分析,等价于[]。- 数组会替换默认值;如果你想在内置默认值的基础上扩展,记得保留
'...'。
内置语法也是通过同一套机制实现的。'...' 这个占位符可以展开为以下条目:
下面这些规则说明了自定义语法的含义:
- 末尾带
()表示匹配调用语法;末尾不带()表示匹配构造器语法。'worker'会匹配new worker(new URL("./worker.js", import.meta.url))。'worker()'会匹配worker(new URL("./worker.js", import.meta.url))。
- 也支持成员语法,但根对象必须是一个自由变量。
'foo.bar'会匹配new foo.bar(new URL("./worker.js", import.meta.url))。'foo.bar()'会匹配foo.bar(new URL("./worker.js", import.meta.url))。
- 可以使用
*按变量名精确匹配根对象。和普通成员语法不同,这里的根对象是一个已声明变量,而不是自由变量。'*foo.bar()'会匹配const foo = new WorkletContext(); foo.bar(new URL("./processor.js", import.meta.url))。- 目前仅支持调用语法,构造器语法如
'*foo.bar'暂不支持。
- 可以使用
from来匹配来自某个精确 ESM source 的导入绑定。'Foo from pkg'会匹配import { Foo } from 'pkg'; new Foo(new URL("./worker.js", import.meta.url))。'default from pkg'会匹配import Foo from 'pkg'; new Foo(new URL("./worker.js", import.meta.url))。'foo() from pkg'会匹配import { foo } from 'pkg'; foo(new URL("./worker.js", import.meta.url))。
下面的示例展示了这些自定义语法规则在实际中的用法。
前几个示例基于内置语法。实际使用中,你不需要把它们再写进配置里,因为它们已经包含在默认的 '...' 中。这里展示它们只是为了说明自定义语法规则是如何工作的:
-
内置构造器语法:
Worker和SharedWorkerWorker和SharedWorker都是构造器,而不是函数,因此对应的语法字符串末尾不需要带()。 -
内置调用语法:
navigator.serviceWorker.register()这个例子展示了为什么末尾的
()很重要:register()是函数调用,而不是构造器。 -
内置导入语法:
Worker from worker_threads这个例子展示了
from规则。import source 必须精确匹配。
下面这些示例展示了一些生态中常见、可以通过自定义语法支持的模式:
-
CSS Worklet
CSS.paintWorklet.addModule()是一个直接的成员函数调用,因此配置字符串末尾需要带()。rspack.config.mjs -
AudioWorklet
和 CSS Worklet 不同,
audioContext.audioWorklet.addModule(...)中的根对象不是自由变量,而是由const audioContext = new AudioContext();声明出来的变量。因此,自定义语法需要以*开头,用来表示根对象是一个已声明变量。rspack.config.mjs -
从第三方包导入 worker
下面这些例子展示了
from在不同导入方式下是如何工作的。rspack.config.mjs
worker-loader
worker-loader 仅作为项目迁移到 Rspack 的临时便捷方案,推荐使用 new Worker() 语法。
Rspack 也支持了 worker-loader,不过由于 worker-loader 已不再维护,请使用 worker-rspack-loader 进行替换。
使用 resolveLoader 替换 worker-loader 为 worker-rspack-loader:

