rust-native-wasm-loader
This is a webpack loader that loads Rust code as a WebAssembly module. It uses the native Rust
support for compiling to wasm32
and does not require Emscripten.
Usage
If you already know how to use Rust and Webpack, read the "Short version" of this section. If you want a full example, read the "Long version."
Short version
Add both this loader and wasm-loader
to your Webpack loaders in webpack.config.js
:
moduleexports = // ... module: rules: test: /\.rs$/ use: loader: 'wasm-loader' loader: 'rust-native-wasm-loader' options: release: true
Then, specify that your Rust library should be a cdylib
in Cargo.toml
:
[lib]crate-type = ["cdylib"]
Now you can import any functions marked with #[no_mangle]
as WebAssembly functions:
;
Available loader options
release
:boolean
; whether to compile the WebAssembly module in debug or release mode; defaults tofalse
.gc
:boolean
; whether to runwasm-gc
on the WebAssembly output. Reduces binary size but requires installing wasm-gc. Defaults tofalse
and is a no-op inwasmBindgen
orcargoWeb
mode.target
:string
; the Rust target to use; this defaults towasm32-unknown-unknown
wasmBindgen
:boolean
orobject
; usewasm-bindgen
to post-process the wasm file. This probably means that you need to chain this loader withbabel-loader
as well sincewasm-bindgen
outputs ES6 (or typescript).wasmBindgen.debug
:boolean
; runwasm-bindgen
in debug mode.wasmBindgen.wasm2es6js
:boolean
; usewasm2es6js
to inline the wasm file into generated Javascript. Useful if webpack is not configured to load wasm files via some other loader.wasmBindgen.typescript
:boolean
; emit a typescript declaration file as part of the build. This file will automatically be referenced, and in a way thatts-loader
will pick it up but it's still possible to treat the output from this loader like a normal Javascript module compatible withbabel-loader
.
cargoWeb
:boolean
orobject
; usecargo-web
to compile the project instead of only building awasm
module. Defaults tofalse
.cargoWeb.name
:string
; the file name to use for emitting the wasm file forcargo-web
, e.g.'static/wasm/[name].[hash:8].wasm'
.cargoWeb.regExp
:string
; a regexp to extract additional variables for use inname
.
Long version
First, you need Rust installed. The easiest way is to follow the instructions at rustup.rs.
Then, you need to add support for WebAssembly cross-compilation. At the time of writing, this
requires using the nightly
compiler:
rustup toolchain install nightlyrustup target add wasm32-unknown-unknown --toolchain nightly
The next step is to integrate a cargo/node project. Let's assume we don't already have one, so we create one:
cargo init addcd add
We can add the Rust code that should be available in the WebAssembly module to src/lib.rs
. All
functions that should be reachable from WebAssembly should be marked with #[no_mangle]
:
pub fn add(a: i32, b: i32) -> i32 { eprintln!("add({:?}, {:?}) was called", a, b); a + b}
Then, specify that your Rust library should be a cdylib
in Cargo.toml
:
[lib]crate-type = ["cdylib"]
Now you can actually start to use this loader. This loader itself does not create Javascript code
for loading a WebAssembly module, so you need to compose it with another loader, like wasm-loader
:
yarn inityarn add --dev webpackyarn add --dev rust-native-wasm-loader wasm-loader
The loaders can be registered the usual way by adding them to your webpack.config.js
:
const path = ; moduleexports = entry: './src/index.js' output: filename: 'index.js' path: path module: rules: test: /\.rs$/ use: loader: 'wasm-loader' loader: 'rust-native-wasm-loader' options: release: true ;
You can now import the WebAssembly module by using the main .rs
file from your Cargo project
(lib.rs
or main.rs
); e.g. from your index.js
:
;
You can now run webpack and the resulting code from node.js or a browser:
$ yarn run webpack$ node dist/index.jsreturn value was 5
wasm-bindgen
experimental support
You can use experimental wasm-bindgen
support with the following options:
test: /\.rs$/ use: loader: 'babel-loader' options: compact: true loader: 'rust-native-wasm-loader' options: release: true wasmBindgen: wasm2es6js: true
The loader now uses wasm-bindgen
to build the project. If you are using webpack 4, it has experimental native support for importing WASM files, so you probably
don't need the wasm2es6js
flag. If you are using webpack 3 (or bundling for Chrome and it's 4K limit on main thread WASM), it is needed in order to inline
the loading of the wasm file correctly. By using wasm2es6js
, the loader returns a normal Javascript module that can
be loaded like so:
wasmBooted;
cargo-web
experimental support
You can use experimental cargo-web
support with the following options:
loader: 'rust-native-wasm-loader' options: cargoWeb: true name: 'static/wasm/[name].[hash:8].wasm'
The loader now uses cargo-web
to build the project, and as a result needs to emit the wasm file
separately. The loader now returns a normal Javascript module that can be loaded like so:
loadWasm;