Building and Composing Components

33.1 Rust (cargo-component / wit-bindgen)

Alternatively, use plain cargo build --target wasm32-wasip2 with the wit-bindgen macro (wit_bindgen::generate!).

cargo component new --lib calculator && cd calculator
# place calculator.wit in wit/
cargo component build --release
wasm-tools component wit target/wasm32-wasip1/release/calculator.wasm   # inspect the interface
// src/lib.rs (generated bindings via cargo-component)
#[allow(warnings)]
mod bindings;
use bindings::exports::example::calculator::ops::{Guest, Point, Shape, GuestAccumulator};
use std::cell::Cell;

struct Component;

impl Guest for Component {
    type Accumulator = Acc;
    fn area(s: Shape) -> f64 {
        match s {
            Shape::Circle(r) => std::f64::consts::PI * r * r,
            Shape::Rectangle((w, h)) => w * h,
        }
    }
    fn midpoint(a: Point, b: Point) -> Point { Point { x: (a.x + b.x) / 2.0, y: (a.y + b.y) / 2.0 } }
    fn parse_number(input: String) -> Result<f64, String> { input.trim().parse().map_err(|e| format!("{e}")) }
    fn find(items: Vec<String>, needle: String) -> Option<u32> {
        items.iter().position(|i| *i == needle).map(|p| p as u32)
    }
}

struct Acc(Cell<f64>);
impl GuestAccumulator for Acc {
    fn new(start: f64) -> Self { Acc(Cell::new(start)) }
    fn add(&self, value: f64) { self.0.set(self.0.get() + value); }
    fn total(&self) -> f64 { self.0.get() }
}

bindings::export!(Component with_types_in bindings);

33.2 Other Languages

ComponentizeJS (jco componentize) builds components from JS (embeds StarlingMonkey)

TinyGo -target wasip2 + wit-bindgen-go wit-bindgen c + wasi-sdk + wasm-tools component new Java/Kotlin, MoonBit

33.3 Running Components in JS (jco)

jco transpile calculator.wasm -o dist/calculator     # component → ES module + core wasm
jco run cli-app.wasm                                 # run a wasi:cli component in Node
jco serve http-app.wasm                              # run a wasi:http component
import { ops } from "./dist/calculator/calculator.js";
console.log(ops.area({ tag: "circle", val: 2 }));
const acc = new ops.Accumulator(10); acc.add(5); console.log(acc.total());

33.4 Composition

Registries: OCI registries (wkg oci push, wasm-pkg-tools), with wa.dev-style package registries for WIT packages and components.

Use cases: polyglot plugins, sandboxed third-party libraries ("shared-nothing linking"), platform SDKs defined by WIT worlds (Spin, wasmCloud, Fastly, Shopify), virtualized I/O for testing.

# Plug a component's imports with another component's exports
wac plug app.wasm --plug calculator.wasm -o composed.wasm
wasm-tools compose app.wasm -d calculator.wasm -o composed.wasm   # older tool
wasm-tools component new core.wasm --adapt wasi_snapshot_preview1.reactor.wasm -o comp.wasm   # wrap a p1 module