WebAssembly
Rslib 支持构建引用 WebAssembly(.wasm)模块的库。
你可以在源码中使用 WebAssembly ESM Integration 语法:
API
在 lib 配置中使用 wasm 配置 Rslib 如何处理直接导入的 .wasm 模块。
- 类型:
当未配置 mode 时,Rslib 会根据 bundle 选择默认 mode:
如果需要显式控制行为,可以设置 wasm.mode:
wasm.mode
mode 用于控制直接 .wasm import 的处理方式。
compile:Rspack 解析.wasm模块,并生成 JavaScript 胶水代码和运行时加载逻辑。详见 Compile mode。preserve:Rslib 在产物中保留.wasmimport,并输出二进制文件,交给支持 WebAssembly ESM Integration 的下游工具或运行时处理。详见 Preserve mode。
mode 仅对 ESM 产物生效,详见 使用限制。
Compile mode
在 compile mode 下,Rspack 会编译 .wasm 模块,并生成负责加载和实例化 WebAssembly 的 JavaScript 代码。
Compile mode 会将 WebAssembly 二进制文件作为资源输出。输出路径遵循 Rsbuild 的 output.distPath.wasm(默认 static/wasm)和默认 wasm 文件名模板,例如:
你可以通过 output.distPath 和 output.filename 自定义目录和文件名。
该模式适用于下游用户没有再使用构建工具的场景,例如在 Node.js 应用中直接导入该库,或在浏览器中直接加载 ESM 产物。
在 compile mode 下,Rslib 会生成用于加载 .wasm 文件的运行时代码。具体加载方式会根据 Rslib 的 output.target 配置决定:
- Web target 会生成通过
fetch加载.wasm的运行时代码。 - Node target 会生成通过 Node.js 异步文件系统 API 加载
.wasm的运行时代码。
Preserve mode
在 preserve mode 下,Rslib 不会为直接 .wasm import 生成 WebAssembly 加载运行时,而是在 JavaScript 产物中保留真实的 .wasm import,并输出二进制文件。
产物布局取决于 bundle。
Bundle 模式
在 bundle 模式下,源码文件会被打包进 JavaScript chunk,因此 .wasm 二进制会作为资产输出,并使用带 content hash 的文件名:
content hash 的 asset 布局会破坏依赖相对 module specifier 的 .wasm 模块的 WebAssembly ESM Integration 语义(例如部分 wasm-bindgen 产物,其 .wasm 文件必须与 JavaScript glue 文件保持相邻)。将二进制以 hash 文件名移动到资产目录后,这些相对路径会断裂。对于这类模块,请使用 bundleless 模式 或 compile 模式。
Bundleless 模式
在 bundleless 模式下,Rslib 会按照源码相对路径和原文件名将 .wasm 文件 copy 到产物目录:
该布局会让 .wasm 文件与 JavaScript 文件保持相邻,适用于依赖相对 module specifier 的 WebAssembly 包,例如部分 wasm-bindgen 产物需要让 .wasm 文件与 JavaScript glue 文件保持相邻。
支持的导入形式
Rslib 在 ESM 产物中支持以下 WebAssembly ESM Integration 导入形式。
静态导入与导出
当你希望通过 ESM binding 访问实例化后的 WebAssembly 导出时,可以使用静态导入和导出:
动态导入
也支持动态导入:
在 preserve 模式下,Rslib 会保留 .wasm 模块的导入语义,但生成的 JavaScript 中仍可能包含用于加载 JavaScript chunk 的 bundler runtime。
Source phase import
import source 是 WebAssembly ESM Integration 的一部分。它导入的是编译后的 WebAssembly.Module,而不是实例化后的导出对象。
当你需要自行实例化模块时(例如传入自定义 import object),可以使用这种语法:
也支持通过 import.source() 进行动态 source phase import:
在 compile 模式下,Rspack 会将这种语法转换为 JavaScript 产物,因此最终消费方不需要原生支持 source phase import。
在 preserve 模式下,Rslib 会在产物中保留 source phase import,因此下游运行时或打包工具必须支持这种语法。
运行时支持:
打包工具支持:
TypeScript 当前不能解析 import source 或 import.source()。请在 JavaScript 文件中编写 source phase import,或使用支持该语法的工具链。
使用 wasm-bindgen
wasm-bindgen 是 Rust 和 WebAssembly 生态中的工具,它提供了一站式的 WebAssembly 开发方案。
在 Rslib 中使用 wasm-bindgen 时,建议使用 --target bundler 生成产物:
bundler target 会生成以 ES module 形式导入 .wasm 文件的 JavaScript glue 产物,这和 Rslib 的 WebAssembly 处理模型匹配。
wasm-bindgen 产物中,.wasm 二进制与 JavaScript glue 文件之间存在相对依赖:glue 会 import .wasm,.wasm 又会 import 回 glue。某个 Rslib 配置能否保持这种关系,取决于 mode 与 bundle 的组合:
在 compile 模式下,Rspack 会在构建时解析 .wasm 模块及其 glue 依赖,因此无论 bundle 还是 bundleless 都能正常工作。
如果你希望在产物中保留原始的 wasm-bindgen 文件、且不生成加载运行时,可以使用 bundleless preserve 模式:
不要对 wasm-bindgen 产物使用 bundle 模式 的 preserve。content hash 的 asset 布局会将 .wasm 文件移离 glue 文件,破坏生成产物中的相对 module specifier。请改用 compile 模式或 bundleless preserve 模式。
TypeScript 类型声明
TypeScript 默认不提供 .wasm 文件的模块类型声明。你可以在 .wasm 文件旁添加 .d.wasm.ts 扩展名的声明文件,这需要在 tsconfig.json 中开启 allowArbitraryExtensions:
使用限制
- 直接 WebAssembly ESM Integration import 仅支持 ESM 产物;
cjs、umd、iife和mf格式不支持直接.wasmimport/export。当为非 ESM 格式设置mode时,该配置会被忽略,并回退到 compile 行为。
