Tutorial

WebAssembly Tutorial

A practical tutorial on WebAssembly using Rust, covering browser and server-side use. Walks through the WAT text format, linear memory, JS interop with wasm-bindgen, wasm-pack, WASI, server runtimes (Wasmtime, Wasmer), the Component Model, and the tooling and patterns that keep real Wasm modules small, fast, and maintainable.

Tutorial·Difficulty: Intermediate·12 chapters·Updated Apr 19, 2026

Chapters

About this tutorial

A practical tour of WebAssembly using Rust, from your first compiled module to running Wasm on a server with WASI.

Who This Is For

  • Developers who've heard Wasm is "fast" and "portable" and want to see what that actually means
  • Rust programmers curious about compilation targets beyond native binaries
  • Engineers evaluating Wasm for edge compute, plugin systems, or sandboxed code execution
  • Anyone building for the browser who's pushing the limits of JS performance

Contents

Fundamentals

  1. Introduction: What Wasm is, why it exists, toolchain, first module
  2. WAT and Binary: The text format, binary structure, module anatomy
  3. Linear Memory: Memory model, passing strings and arrays across the boundary

Core Concepts

  1. Rust to Wasm: Compiling Rust to Wasm with no glue code
  2. JavaScript Interop: Instantiating Wasm in browsers, calls in both directions
  3. wasm-bindgen: The Rust–JS bridge, JsValue, complex types, async
  4. wasm-pack and Bundlers: Building for npm, webpack, Vite

Advanced

  1. WASI: System interface for server-side Wasm
  2. Server Runtimes: Wasmtime, Wasmer, WasmEdge
  3. The Component Model: WIT, composable Wasm

Ecosystem

  1. Ecosystem: Other source languages, tooling, real-world uses

Mastery

  1. Best Practices: Performance, size, debugging, anti-patterns

How to Use This Tutorial

  1. Read sequentially. Each chapter builds on the last
  2. Build every example. Wasm is a concrete artifact; poking at real .wasm files makes the concepts click
  3. Install the tooling early. Chapter 1 gets you a working toolchain in about 10 minutes

Quick Reference

Toolchain Setup

# Rust with the Wasm target
rustup target add wasm32-unknown-unknown   # for browsers
rustup target add wasm32-wasip1             # for WASI (server)

# wasm-bindgen CLI (browser interop)
cargo install wasm-bindgen-cli

# wasm-pack (npm-friendly builds)
cargo install wasm-pack

# WABT (WAT <-> binary)
brew install wabt          # macOS
# or build from github.com/WebAssembly/wabt

# A server runtime
brew install wasmtime      # or: curl https://wasmtime.dev/install.sh -sSf | bash

Hello Wasm (Rust, no helpers)

// src/lib.rs
#[no_mangle]
pub extern "C" fn add(a: i32, b: i32) -> i32 {
    a + b
}
# Cargo.toml
[lib]
crate-type = ["cdylib"]
cargo build --target wasm32-unknown-unknown --release
# target/wasm32-unknown-unknown/release/hello.wasm

Inspect it:

wasm2wat target/wasm32-unknown-unknown/release/hello.wasm | head

Common Patterns

// Export a function
#[no_mangle]
pub extern "C" fn multiply(a: i32, b: i32) -> i32 { a * b }

// Import a JS function (browser)
extern "C" {
    fn console_log(ptr: *const u8, len: usize);
}

// With wasm-bindgen (see Chapter 6):
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn greet(name: &str) -> String {
    format!("Hello, {name}!")
}
# Run a WASI module on the server
wasmtime run my_module.wasm

# Optimize size and speed
wasm-opt -O3 -o out.wasm in.wasm

# Disassemble to text
wasm2wat in.wasm -o out.wat

Additional Resources

Versions

This tutorial is written for Rust 1.75+, wasm-bindgen 0.2+, wasm-pack 0.12+, and Wasmtime 20+. The Component Model examples assume WASI Preview 2. Older versions work with adjustments, noted where relevant.