Cheat Sheet

Quick reference for Rust + WebAssembly development

Project Setup

Cargo.toml
[lib]
crate-type = ["cdylib"]

[dependencies]
wasm-bindgen = "0.2"
web-sys = { version = "0.3", features = ["Window", "Document"] }
js-sys = "0.3"
wasm-bindgen-futures = "0.4"
Terminal
# Install
cargo install wasm-pack

# Build
wasm-pack build --target web

# Build for bundler (Webpack, Vite)
wasm-pack build --target bundler

#[wasm_bindgen] Attributes

UsageRustJavaScript
Export function#[wasm_bindgen] pub fn foo()foo()
Struct as class#[wasm_bindgen] pub struct Foonew Foo()
Constructor#[wasm_bindgen(constructor)]new Foo()
Getter#[wasm_bindgen(getter)]obj.name
Setter#[wasm_bindgen(setter)]obj.name = x
Import JS functionextern "C" { fn alert(s: &str); }window.alert()
JS namespace#[wasm_bindgen(js_namespace = console)]console.log()
Rename#[wasm_bindgen(js_name = "myFunc")]myFunc()
Skip export#[wasm_bindgen(skip)]Hidden

Type Mapping

RustJSCost
i32, f64, boolnumber, booleanFree
i64, u64BigIntFree
&strstring (JS→Rust)Copy
Stringstring (Rust→JS)Copy
Vec<u8>, &[u8]Uint8ArrayCopy
Vec<f64>Float64ArrayCopy
JsValueanyRef
Option<T>T | undefinedVaries
Result<T, JsValue>T (throws on Err)Varies
#[wasm_bindgen] structclassPointer
Closure<dyn FnMut()>FunctionAlloc

Common Patterns

Export Function
#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 { a + b }
Call from JS
import init, { add } from './pkg/my_wasm.js';
await init();
add(2, 3); // → 5
Import console.log
#[wasm_bindgen]
extern "C" {
    #[wasm_bindgen(js_namespace = console)]
    fn log(s: &str);
}
Error Handling
#[wasm_bindgen]
pub fn run() -> Result<(), JsValue> {
    // ? converts Err to JS exception
    let el = document.create_element("div")?;
    Ok(())
}

Common web-sys Features

WindowDocumentElementHtmlElementHtmlCanvasElementCanvasRenderingContext2dconsoleNodeStorageMouseEventKeyboardEventRequestRequestInitResponseHeadersUrlHistoryLocation

Performance Tips

  • Prefer primitives (i32, f64, bool) — zero cost
  • Use flat arrays (Vec<f64>) for bulk data transfer
  • Reuse buffers — don't allocate Vec per frame
  • Structs pass as pointers — no data copy
  • Avoid frequent string passing — each crossing copies data
  • Don't pass structured data via JSON — use flat arrays