Rust WebAssembly
WebAssembly is a compact instruction language that browsers run. Rust can compile straight to WebAssembly, so the same Rust code runs inside a page.
A new target for the compiler
A target names the machine your code will run on. This one names the browser's virtual machine:
// in your terminal:
// $ rustup target add wasm32-unknown-unknownThe crate builds as a library
A Wasm crate has no main. It is a library that a page loads. The rlib half keeps normal cargo test working:
// Cargo.toml
[lib]
crate-type = ["cdylib", "rlib"]
[dependencies]
wasm-bindgen = "0.2"Mark what JavaScript may call
The attribute is the export sticker. Only marked items cross to JavaScript:
#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
a + b
}One command builds the package
wasm-pack compiles for the target. It then runs wasm-bindgen and writes the package:
// in your terminal:
// $ wasm-pack build
// pkg/ now holds the .wasm file, the JS glue,
// and a package.json for the page or npmThe page calls your Rust
The page loads the module first. Then your functions feel like plain JavaScript functions:
import init, { add } from "./pkg/greeter.js";
await init();
console.log(add(2, 3));Example
// Cargo.toml: [lib] crate-type = ["cdylib", "rlib"]
// Cargo.toml: [dependencies] wasm-bindgen = "0.2"
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
#[wasm_bindgen]
pub fn greet(name: &str) -> String {
format!("Hello, {name}!")
}Key points
- WebAssembly: a compact binary format that browsers run next to JavaScript, at close to native speed
- Rust fits it well: no garbage collector, no runtime, and small output files
- Use rustup target add to teach your compiler the new target: wasm32-unknown-unknown
- wasm-pack is the workflow tool.
- It builds the crate.
- It generates the JavaScript glue.
- It packs the result into a pkg folder
- JavaScript stays in charge of the page: it loads the module and calls your functions
- A .wasm file cannot touch the page, the files, or the network by itself.
In this example, the crate is the whole greeter. The use line brings in the wasm_bindgen attribute. add takes two whole numbers and returns their sum. greet takes text and builds a greeting String. wasm-pack build turns this file into a package. A JavaScript host then calls add(2, 3) and greet("Ferris"). The console shows the two results: 5 and Hello, Ferris!. Nothing here runs on your machine. The same Rust code runs inside the page.
Note
Every outside power arrives through JavaScript.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Rust Playground
Exercise
What does the target name wasm32-unknown-unknown tell the compiler?