wasm-bindgen
Bridge Rust and JavaScript with wasm-bindgen macros and glue code generation.
Search across all documentation pages
Bridge Rust and JavaScript with wasm-bindgen macros and glue code generation.
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn greet(name: &str) -> String {
format!("Hello, {name}!")
}wasm-pack build --target webWhen to reach for this: Browser WASM that must call JS APIs and expose Rust functions to JavaScript.
use wasm_bindgen::prelude::*;
use serde::{Deserialize, Serialize};
#[wasm_bindgen]
pub struct Counter {
value: u32,
}
#[wasm_bindgen]
impl Counter {
#[wasm_bindgen(constructor)]
pub fn new() -> Counter {
Counter { value: 0 }
}
pub fn increment(&mut self) {
self.value += 1;
}
pub fn value(&self) -> u32 {
self.value
}
}
#[wasm_bindgen]
pub fn parse_json(input: &str) -> Result<JsValue, JsValue> {
let data: serde_json::Value = serde_json::from_str(input)
.map_err(|e| JsValue::from_str(&e.to_string()))?;
Ok(JsValue::from_serde(&data)?)
}import init, { Counter, parse_json } from "./pkg/mylib.js";
await init();
const c = new Counter();
c.increment();
console.log(c.value());
console.log(parse_json('{"ok":true}'));What this demonstrates:
#[wasm_bindgen] exports Rust types to JS classesconstructor maps to new Counter()JsValue crosses the boundary for dynamic JSONwasm-pack generates TypeScript-friendly JS wrappers| Rust | JavaScript |
|---|---|
&str / String | string |
u32 / i32 | number |
bool | boolean |
Vec<u8> | Uint8Array |
#[wasm_bindgen] struct | class |
#[wasm_bindgen]
extern "C" {
fn alert(s: &str);
#[wasm_bindgen(js_namespace = console)]
fn log(s: &str);
}String, Vec) over long-lived borrows.Result<JsValue, JsValue> to JS.wasm-bindgen-futures requires Send futures. Fix: Use spawn_local for DOM futures.from_serde needs serde-wasm-bindgen in modern stacks. Fix: Use serde-wasm-bindgen for performance.--release for browser deploys.| Alternative | Use When | Don't Use When |
|---|---|---|
Raw extern "C" exports | Minimal no-JS-glue modules | Rich JS interop |
wasm-bindgen-rayon | Parallel compute in browsers with threads | Single-threaded DOM apps |
| Compile to WASI instead | Server-side WASM | Browser DOM access needed |
wasm-bindgen targets browsers and JS. WIT/Component Model uses wit-bindgen for portable interfaces.
Mark structs with #[wasm_bindgen] and expose methods on impl blocks.
Use wasm-bindgen-futures and js_sys::Promise bridging.
Yes for most modules. wasm32-unknown-unknown has no OS but std mostly works with shims.
Use wasm-bindgen-test in headless browsers or wasmtime for non-DOM logic.
Enable debug symbols in dev profile. wasm-pack build --dev includes names for stack traces.
Workspace members can each be WASM crates. Link with rlib and one cdylib entry.
Closure::wrap passes Rust callbacks to JS event handlers. Remember to forget or store to keep alive.
Use js_sys::BigInt for 64-bit integers beyond JS Number safe range.
wasm-pack build --target bundler for webpack/vite. --target web for direct browser ES modules.
Stack versions: This page was written for Rust 1.97.0 (edition 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, and Polars 0.46+.
Reviewed by Chris St. John·Last updated Jul 16, 2026