← Back to Lessons Lesson 28 of 28
Advanced api

Wasm Component Model

The Problem with Current Wasm

Today's WebAssembly only supports 4 types: i32, i64, f32, f64. Everything else (strings, structs, arrays) requires manual encoding:

Current: Rust String → UTF-8 bytes → pointer + length → JS decode
Future:  Rust Stringstring (native Wasm type) → JS string

wasm-bindgen solves this for Rust↔JS, but it's Rust-specific. A Go module can't call a Rust module's functions without custom glue.

What the Component Model Fixes

Problem Current Component Model
Types Only i32/i64/f32/f64 Strings, lists, records, variants, options, results
Interop Language-specific glue Language-agnostic WIT interfaces
Composition Monolithic modules Composable components that import/export
Dependencies Manual linking Package registry (warg)

WIT: WebAssembly Interface Types

WIT is the interface definition language for components:

// my-api.wit
package example:my-api;

interface types {
    record user {
        name: string,
        age: u32,
        email: option<string>,
    }

    enum role {
        admin,
        editor,
        viewer,
    }

    variant error {
        not-found(string),
        permission-denied,
        internal(string),
    }
}

interface users {
    use types.{user, role, error};

    create-user: func(name: string, age: u32) -> result<user, error>;
    get-user: func(id: u32) -> option<user>;
    list-users: func() -> list<user>;
}

world my-app {
    import wasi:http/outgoing-handler;
    export users;
}

WIT Types

WIT type Description Example
string UTF-8 string "hello"
bool Boolean true
u8..u64, s8..s64 Integers 42
f32, f64 Floats 3.14
list<T> Dynamic array list<string>
option<T> Nullable option<u32>
result<T, E> Success or error result<user, error>
record Named fields (struct) record { name: string }
variant Tagged union (enum) variant { a(u32), b }
tuple<T, U> Anonymous tuple tuple<string, u32>

Building a Component with Rust

# Install cargo-component
cargo install cargo-component

# Create a new component project
cargo component new my-component
cd my-component
// src/lib.rs
#[allow(warnings)]
mod bindings;

use bindings::Guest;

struct Component;

impl Guest for Component {
    fn greet(name: String) -> String {
        format!("Hello, {}!", name)
    }
}

bindings::export!(Component with_types_in bindings);
# Build the component
cargo component build --release

# The output is a .wasm component (not a core module)

Composing Components

Multiple components can be composed together:

┌─────────────────┐     ┌─────────────────┐
│  Auth Component  │────▶│  API Component   │
│  (Rust)          │     │  (Go)            │
└─────────────────┘     └────────┬────────┘
                                 │
                        ┌────────▼────────┐
                        │  DB Component    │
                        │  (Python)        │
                        └─────────────────┘

Each component:

  • Exposes a typed WIT interface
  • Can be written in any language
  • Is sandboxed — can only access what it imports
  • Can be replaced without changing other components

Timeline

Status Feature
✓ Stable Core Wasm (modules, memory, functions)
✓ Stable WASI preview 1 (file I/O, env, args)
✓ Stable Component Model specification
✓ Available cargo-component, jco, wasmtime support
🔄 In progress WASI preview 2 (HTTP, sockets, key-value)
🔄 In progress warg package registry
📋 Planned Browser support for components
📋 Planned Component linking in bundlers

Why This Matters

The Component Model turns Wasm from "fast code in the browser" into a universal software component format:

  • Write a Rust image processor → use it from Python, Go, JS
  • Build a plugin system → users write plugins in any language
  • Microservices → each service is a sandboxed Wasm component
  • Edge computing → compose components at the CDN edge

Try It

Click Run to see the Component Model overview — what it provides, WIT syntax, and the tools available. This is the future direction of WebAssembly.

Try It

Chapter Quiz

Pass all questions to complete this lesson