Web Development7 min read

WebAssembly (WASM)

Compile Rust, C++, or Go to WebAssembly for near-native browser performance. Build WASM modules with wasm-pack and integrate with JavaScript.

webassemblywasmrustperformance

WebAssembly (WASM) enables near-native performance in the browser by running compiled code from Rust, C++, Go, or AssemblyScript. It's used for compute-heavy workloads: video encoding, image processing, cryptography, game engines, and scientific computing.

Use WASM for specific performance-critical inner loops, not for entire applications. Rust + wasm-pack is the best developer experience. Keep JS↔WASM boundary calls minimal (crossing the boundary has overhead). Profile before rewriting in WASM.

Workflow

  1. Compile Rust to WASM with wasm-packwasm-pack automates the Rust → WASM → npm package pipeline, producing optimized modules with JS glue code.
  2. Integrate WASM into JavaScriptThe generated JS glue handles memory management and type conversion between JS and WASM.
  3. Work with complex types and shared memoryPassing objects and arrays between JS and WASM requires explicit memory management.
  4. Optimize WASM bundle sizeWASM modules can be large; optimization is critical for web performance.
  5. Use Web Workers for background computationWASM running in the main thread blocks UI; Web Workers enable truly parallel computation.

Output Format

Rust library with wasm-bindgen, wasm-pack build producing npm package, integrated into web bundler, loaded asynchronously, computation in Web Worker.

Examples

Rust WASM: `#[wasm_bindgen] pub fn hash_password(password: &str) -> String { use sha2::{Sha256, Digest}; format!("{:x}", Sha256::digest(password.as_bytes())) }`
JS usage: `import init, { hash_password } from "./pkg/crypto_wasm"; await init(); const hash = hash_password("secret123");`
Image processing: `#[wasm_bindgen] pub fn grayscale(data: &mut [u8]) { for i in (0..data.len()).step_by(4) { let gray = (data[i] as u16 * 299 + data[i+1] as u16 * 587 + data[i+2] as u16 * 114) / 1000; data[i] = gray as u8; data[i+1] = gray as u8; data[i+2] = gray as u8; } }`

Edge Cases & Gotchas

  • WASM startup time: initialization is async and can take 50-200ms for large modules; show loading state and pre-load WASM during idle time with `<link rel="modulepreload">`
  • Debugging: WASM debugging in Chrome DevTools requires DWARF debug info; enable with `wasm-pack build --debug` in development
  • Memory leaks: Rust WASM objects exposed to JS must be explicitly freed: `const obj = wasmModule.MyStruct.new(); obj.process(); obj.free();` - forget to free and memory leaks

When to Break These Rules

  • For simple data transformation or string processing, JavaScript (especially with V8's JIT) is fast enough and infinitely simpler to debug than cross-language WASM boundaries.

Reference Files

  • Rust and WebAssembly book: https://rustwasm.github.io/docs/book/
  • wasm-pack: https://rustwasm.github.io/wasm-pack/
  • MDN WebAssembly: https://developer.mozilla.org/en-US/docs/WebAssembly
  • wasm-bindgen: https://rustwasm.github.io/docs/wasm-bindgen/

More skills in this library

Browse all technical skills - Mobile, AI/ML, Web, Backend, Design, and Product.