WebAssembly
Rslib supports WebAssembly (.wasm) modules used with the WebAssembly ESM Integration proposal syntax.
Source code that uses the WebAssembly ESM Integration proposal syntax can only be built as ESM output, so format must be 'esm' (the default value).
This is because compiling and instantiating a .wasm module is asynchronous. A JavaScript module that statically imports it also becomes an async module, and asynchronous evaluation propagates through the importing module graph. CommonJS, UMD, and IIFE do not provide module evaluation and export semantics equivalent to ESM async modules, so these imports cannot be transformed reliably.
Import wasm in JavaScript file
You can import a .wasm module using the ESM module import syntax:
Rslib supports the following import forms for .wasm modules.
Static import and export
Access instantiated exports through standard ESM bindings:
Dynamic import
Source phase import
import source is part of WebAssembly ESM Integration, and Rspack provides first-class support for it. It imports the compiled WebAssembly.Module instead of the instantiated exports, so you can instantiate it yourself with a custom import object:
Dynamic source phase import is also supported through import.source():
TypeScript does not currently parse import source or import.source(). Write source phase imports in JavaScript files, or use a toolchain that supports the syntax.
Configure output
Rslib provides two modes to emit .wasm modules, controlled by lib.wasm.mode.
- Compile mode: Rspack handles
.wasmimports during the build, generates JavaScript runtime code that loads and instantiates WebAssembly, and emits the binary as a static asset. Consumers do not need to support ESM Integration. - Preserve mode: In bundleless builds, Rslib retains
.wasmESM Integration imports in the JavaScript output and emits the binary as-is. The downstream build tool or runtime is responsible for resolving and loading the.wasmmodule.
The default value depends on bundle:
If the output needs to be consumed directly by a JavaScript runtime such as a browser, use Compile mode. If a bundleless output will be processed by a build tool that supports ESM Integration, such as Rsbuild, or if the target runtime (such as Node.js ^22.19.0 || >=24.5.0) supports this feature natively, you can use Preserve mode. Rslib rejects bundle: true together with wasm.mode: 'preserve'; use Compile mode for bundled output.
Compile mode
In Compile mode, Rspack parses the .wasm module and generates JavaScript glue code that loads and instantiates it at runtime.
The binary is emitted as an asset with a content-hashed filename under output.distPath.wasm (defaults to static/wasm):
The generated loading runtime is derived from output.target:
- For
webtargets,.wasmis loaded withfetch. - For
nodetargets,.wasmis loaded from the file system with async Node.js APIs.
Preserve mode
Preserve mode requires bundle to be false. Rslib does not generate any WebAssembly loading runtime. It keeps a real .wasm import in the JavaScript output and emits the binary as-is.
The .wasm file is copied to the output using the same source-relative path and original filename:
The .wasm filename in Preserve mode is not affected by output.filenameHash.
Rslib updates JavaScript imports to follow the emitted .wasm files, including when output.filename.js places JavaScript in another directory. However, the WebAssembly binary is emitted without modification. If it imports JavaScript, those imports still use their original relative paths and filenames. In this case, do not move or rename the imported JavaScript files in the output. For example, changing index.js to js/index.js or index.mjs would break a WebAssembly import of ./index.js.
Use wasm-bindgen
wasm-bindgen is a tool for building WebAssembly libraries with Rust. The --target option generates output for different runtime environments.
Rslib supports the following targets:
bundler(recommended)moduleweb/experimental-nodejs-module
bundler
The JavaScript glue imports the .wasm file as an ES module, and the .wasm module imports back into the glue for its imports object.
Because of this two-way relative dependency, Preserve mode requires the output to keep the relative path and filename between the .wasm file and its JavaScript glue. In particular, avoid moving the glue with output.filename.js or changing its extension with autoExtension.
module
The JavaScript glue imports the .wasm file with the source phase import syntax, and constructs the imports object entirely in JavaScript. Use Compile mode for bundled output, or Preserve mode for bundleless output.
web / experimental-nodejs-module
The JavaScript glue loads the .wasm file through new URL('./pkg.wasm', import.meta.url). Rslib treats it as a static asset instead of a WebAssembly ESM module.
wasm.mode does not apply in this case.
Type declaration
TypeScript does not provide built-in module declarations for .wasm files. If you use TypeScript, add a declaration file next to the .wasm file using the .d.wasm.ts extension, and enable allowArbitraryExtensions in tsconfig.json:
