wasm-bindgen: Rust meets the DOM
The bridge that makes every Rust web UI framework possible.
wasm-bindgen generates the glue between Rust compiled to WebAssembly and JavaScript. web-sys builds on it to give Rust typed access to browser APIs: the DOM, canvas, fetch, WebGPU. It is the most depended-on crate in this book, with over 5,000 dependents, and nearly every web target here rests on it: Yew, Leptos, Sycamore, winit's web backend and wgpu's browser backend all list it.
use book_error::{Context, Error};
use wasm_bindgen::prelude::*;
// Runs automatically when the .wasm module is loaded in the page. A returned
// error becomes a JavaScript exception (see `From<Error> for JsValue`).
#[wasm_bindgen(start)]
fn run() -> Result<(), Error> {
let document = web_sys::window()
.context("no global `window` (not running in a browser?)")?
.document()
.context("window has no document")?;
let p = document.create_element("p")?;
p.set_text_content(Some("Hello from Rust!"));
document.body().context("document has no <body>")?.append_child(&p)?;
Ok(())
}
fn main() {} Using a browser API takes only a few lines, and you must enable each web-sys type you use as a Cargo feature (here Window, Document, Element, HtmlElement). That keeps the compiled .wasm small, and it is why Rust web frameworks ask you to list features so carefully.
use wasm_bindgen::prelude::*;
// Call *into* JavaScript...
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = console)]
fn log(message: &str);
}
// ...and expose Rust *out* to it.
#[wasm_bindgen]
pub fn greet(name: &str) -> String {
log(&format!("greeting {name}"));
format!("Hello, {name}!")
}
fn main() {} A returned error becomes a JavaScript exception, through the From<Error> for JsValue impl on the error-handling page, instead of a panic that aborts the module. The boundary runs both ways. extern "C" blocks import JavaScript functions into Rust and #[wasm_bindgen] on a function exports it out. Build tools like Trunk or wasm-pack run the wasm-bindgen step for you. Both snippets were compiled for wasm32-unknown-unknown. The crate is still 0.2.x, stable in practice and pre-1.0 on paper.