Rust and WebAssembly
WebAssembly (WASM) lets you run compiled code in the browser at near-native
speed. Rust is one of the best languages for WASM thanks to its small runtime, no garbage
collector, and excellent tooling with wasm-pack and wasm-bindgen.
When to Use Rust + WASM
- Performance-critical code: Image/video processing, physics simulations, crypto
- Existing Rust libraries: Reuse server-side logic in the browser
- CPU-intensive tasks: Data parsing, compression, ML inference
- Gaming: Game engines and real-time rendering
Setting Up
# Install wasm-pack
cargo install wasm-pack
# Or via curl:
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
# Create a new WASM project
cargo new --lib wasm-hello
cd wasm-hello
// Cargo.toml
// [lib]
// crate-type = ["cdylib"]
//
// [dependencies]
// wasm-bindgen = "0.2"
// js-sys = "0.3"
// web-sys = { version = "0.3", features = ["console", "Document", "Element", "HtmlElement", "Window"] }
use wasm_bindgen::prelude::*;
// Export a function to JavaScript
#[wasm_bindgen]
pub fn greet(name: &str) -> String {
format!("Hello, {name} from Rust + WASM!")
}
#[wasm_bindgen]
pub fn fibonacci(n: u32) -> u64 {
match n {
0 => 0,
1 => 1,
_ => {
let mut a: u64 = 0;
let mut b: u64 = 1;
for _ in 2..=n {
let temp = a + b;
a = b;
b = temp;
}
b
}
}
}
// Use JavaScript APIs from Rust
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = console)]
fn log(s: &str);
}
#[wasm_bindgen]
pub fn init() {
log("WASM module initialized!");
}
Building and Using in JavaScript
# Build the WASM package
wasm-pack build --target web # For ES modules
wasm-pack build --target bundler # For webpack/Vite
wasm-pack build --target nodejs # For Node.js
// JavaScript usage (ES modules)
// <script type="module">
// import init, { greet, fibonacci } from './pkg/wasm_hello.js';
//
// async function main() {
// await init();
// console.log(greet("World"));
// console.log("fib(40) =", fibonacci(40));
//
// // Performance comparison
// const start = performance.now();
// const result = fibonacci(45);
// const elapsed = performance.now() - start;
// console.log("WASM fib(45):", result, "in", elapsed, "ms");
// }
// main();
// </script>
DOM Manipulation from Rust
use wasm_bindgen::prelude::*;
use web_sys::{Document, Element, HtmlElement, Window};
#[wasm_bindgen]
pub fn create_element(tag: &str, text: &str) -> Result<(), JsValue> {
let window: Window = web_sys::window().unwrap();
let document: Document = window.document().unwrap();
let body: HtmlElement = document.body().unwrap();
let element: Element = document.create_element(tag)?;
element.set_text_content(Some(text));
element.set_attribute("class", "rust-created")?;
body.append_child(&element)?;
Ok(())
}
#[wasm_bindgen]
pub fn update_counter(id: &str, value: i32) -> Result<(), JsValue> {
let document = web_sys::window().unwrap().document().unwrap();
if let Some(element) = document.get_element_by_id(id) {
element.set_text_content(Some(&value.to_string()));
}
Ok(())
}
Practical WASM Use Cases
use wasm_bindgen::prelude::*;
// Image processing in WASM
#[wasm_bindgen]
pub fn grayscale(pixels: &mut [u8]) {
// pixels is RGBA data from a canvas
for chunk in pixels.chunks_exact_mut(4) {
let r = chunk[0] as f32;
let g = chunk[1] as f32;
let b = chunk[2] as f32;
let gray = (0.299 * r + 0.587 * g + 0.114 * b) as u8;
chunk[0] = gray;
chunk[1] = gray;
chunk[2] = gray;
// chunk[3] is alpha — leave unchanged
}
}
// JSON parsing benchmark
#[wasm_bindgen]
pub fn parse_large_json(data: &str) -> Result {
let value: serde_json::Value = serde_json::from_str(data)
.map_err(|e| JsValue::from_str(&e.to_string()))?;
let count = count_fields(&value);
Ok(count)
}
fn count_fields(value: &serde_json::Value) -> u32 {
match value {
serde_json::Value::Object(map) => {
map.len() as u32 + map.values().map(count_fields).sum::()
}
serde_json::Value::Array(arr) => {
arr.iter().map(count_fields).sum()
}
_ => 0,
}
}
Key Takeaways
- ✅ Rust compiles to small, fast WASM binaries with no GC overhead
- ✅
wasm-packandwasm-bindgenbridge Rust and JavaScript seamlessly - ✅ WASM excels at CPU-intensive tasks: image processing, crypto, parsing, simulations
- ✅
web-sysprovides typed access to browser DOM APIs from Rust - ✅ Build targets: web (ES modules), bundler (webpack/Vite), or nodejs