Instrucciones de origen · Vista previa de solo lectura
name
wasm
description
WebAssembly integration — Rust to WASM with wasm-pack/wasm-bindgen, WASI, browser usage, server-side WASM, and performance considerations
layer
domain
category
performance
triggers
["wasm","webassembly","wasm-pack","wasm-bindgen","wasi","rust wasm","compile to wasm","wasm module","wasm performance"]
inputs
["Performance-critical computation to offload","Source language (Rust, C/C++, Go, AssemblyScript)","Target environment (browser, Node.js, edge, WASI)"]
outputs
["WASM module build configuration","JavaScript/TypeScript bindings","Integration code for browser or server","Performance benchmarks and optimization guidance"]
["Adds wasm-pack or build tooling","Generates .wasm binary files","May require CORS headers for WASM loading"]
WebAssembly Integration Specialist
Purpose
Integrate WebAssembly modules into web and server applications for near-native performance. This skill covers compiling Rust to WASM with wasm-pack and wasm-bindgen, loading WASM in browsers and Node.js, WASI for server-side use, and understanding when WASM is (and is not) the right tool.
When to Use WASM
Use Case
WASM Benefit
Alternative
Image/video processing
5x-20x faster than JS
Canvas API (limited)
Cryptography
Constant-time, fast
SubtleCrypto API (limited algorithms)
Compression (zstd, brotli)
Near-native speed
Node.js native modules
Physics / simulation
Predictable performance
JS with typed arrays
Parsing (markdown, code)
Fast, portable
JS parsers (slower)
PDF generation
Complex layout engine
JS libs (slower, larger)
Simple DOM manipulation
No benefit, adds overhead
Use JavaScript
I/O-heavy operations
No benefit (I/O is async JS)
Use JavaScript
Key Patterns
1. Rust to WASM with wasm-pack
# Install tooling
cargo install wasm-pack
rustup target add wasm32-unknown-unknown
# Create a new WASM library
cargo init --lib my-wasm-lib
# Cargo.toml[package]name = "my-wasm-lib"version = "0.1.0"edition = "2021"[lib]crate-type = ["cdylib", "rlib"]
[dependencies]wasm-bindgen = "0.2"serde = { version = , features = [] }
=
=
= { version = , features = [, , ] }
=
=
=
=
// Direct memory access for maximum performanceasyncfunctionprocessWithSharedMemory(data: Uint8Array) {
const wasm = awaitimport("./pkg/my_wasm_lib.js");
await wasm.default();
// Access WASM linear memory directlyconst memory = wasm.__wbg_get_memory();
const inputPtr = wasm.allocate(data.length);
// Copy data into WASM memoryconst inputArray = newUint8Array(memory.buffer, inputPtr, data.length);
inputArray.set(data);
// Process in-place (no copy)const outputPtr = wasm.process_buffer(inputPtr, data.length);
// Read result from WASM memoryconst outputArray = newUint8Array(memory.buffer, outputPtr, data.length);
const result = newUint8Array(outputArray); // copy out// Free WASM memory
wasm.deallocate(inputPtr, data.length);
wasm.deallocate(outputPtr, data.length);
return result;
}
7. Performance Benchmarking
// Compare JS vs WASM performanceasyncfunctionbenchmark() {
const wasm = awaitimport("./pkg/my_wasm_lib.js");
await wasm.default();
const iterations = 1000;
const input = 40;
// JS implementationfunctionfibonacciJS(n: number): number {
let a = 0, b = 1;
for (let i = 2; i <= n; i++) {
[a, b] = [b, a + b];
}
return n === 0 ? 0 : b;
}
// Benchmark JSconst jsStart = performance.now();
for (let i = 0; i < iterations; i++) fibonacciJS(input);
const jsTime = performance.now() - jsStart;
// Benchmark WASMconst wasmStart = performance.now();
for (let i = 0; i < iterations; i++) wasm.fibonacci(input);
const wasmTime = performance.now() - wasmStart;
console.log(`JS: ${jsTime.toFixed(2)}ms (${iterations} iterations)`);
console.log(`WASM: ${wasmTime.toFixed(2)}ms (${iterations} iterations)`);
console.log(`WASM is ${(jsTime / wasmTime).toFixed(1)}x faster`);
}
Best Practices
Profile before reaching for WASM -- V8 is fast; WASM wins on compute-heavy, tight-loop workloads, not simple logic
Minimize JS-WASM boundary crossings -- Each call has overhead; batch work into single calls
Use SharedArrayBuffer or typed arrays for large data transfers instead of serializing to JSON
Run WASM in a Web Worker for heavy computation to keep the main thread responsive
Optimize for size with opt-level = "z", LTO, and wasm-opt (from binaryen) for smaller downloads
Use wasm-bindgen for ergonomic Rust-JS interop rather than raw extern "C" bindings
Lazy-load WASM modules -- Do not include in the critical path; load on first use
Cache compiled modules -- Use WebAssembly.compileStreaming() for browser caching of compiled WASM
Free resources explicitly -- WASM-exported structs are not garbage-collected; call .free() when done
Use wasm-opt -Oz as a post-processing step to further reduce binary size
Common Pitfalls
Pitfall
Impact
Fix
Expecting WASM to speed up I/O
No improvement (I/O is JS-bound)
Only use WASM for CPU-bound computation
Loading WASM on the main thread synchronously
Blocks rendering
Use WebAssembly.compileStreaming() or Web Workers
Not freeing WASM-exported objects
Memory leak
Call .free() on every wasm_bindgen struct
Serializing large data as JSON across boundary
Slower than JS-only
Use shared memory / typed arrays
Missing CORS headers for .wasm files
Module fails to load
Serve with application/wasm MIME type and proper CORS
Using opt-level = 3 for WASM
Large binary
Use opt-level = "z" or "s" for smaller output
Calling small WASM functions in a tight JS loop
Overhead dominates
Move the loop into WASM
Forgetting asyncWebAssembly in webpack/Next.js
Build errors
Enable the experiment in webpack config
Examples
Example 1: Image Processing Pipeline
1. User uploads image in browser
2. Decode to ImageData via Canvas API (JS)
3. Transfer pixel buffer to Web Worker (zero-copy with transfer)
4. Worker calls WASM for resize + filter (Rust image crate)
5. Worker posts result back (zero-copy transfer)
6. Render processed image to canvas (JS)
Performance: 2048x2048 grayscale — JS: 180ms, WASM: 12ms
Example 2: Markdown Parser on Edge
1. Compile pulldown-cmark (Rust) to WASM with wasm-pack
2. Deploy to Cloudflare Workers (WASM supported natively)
3. Parse markdown to HTML at the edge — 10x faster than JS parsers
4. Cache rendered output at CDN layer
Binary size: 45KB gzipped (after wasm-opt -Oz)