Component Model

WebAssembly モジュールを型安全に結合するための仕様。Core Module が数値型しか扱えない制約を、WIT (型安全な IDL) + Canonical ABI (標準バイナリ表現) + メモリ隔離 (Share-Nothing) で解決する。WASI はこの上に構築された API 群であり、Component Model はその基盤レイヤー。Bytecode Alliance が Wasmtime でリファレンス実装を提供。

なぜ必要か: Core Module の限界

問題Core ModuleComponent Model
型システムi32/i64/f32/f64 のみstring, list, record, variant, resource 等
データ交換線形メモリ共有 + 手動エンコードCanonical ABI で自動マーシャリング
メモリexport して共有可能export 不可 (Share-Nothing)
言語間結合言語ごとに glue codeWIT を共通契約に自動バインディング生成

WIT (WebAssembly Interface Types)

Component Model の IDL。パッケージ、インターフェース、ワールドでコンポーネントの契約を定義する。

基本構造

package my-company:my-api@1.0.0;

interface greeter {
    record person {
        name: string,
        age: u32,
    }
    greet: func(who: person) -> string;
}

world my-service {
    import wasi:http/types@0.2.0;
    export greeter;
}

型システム

分類型
プリミティブbool, u8-u64, s8-s64, f32, f64, char, string
複合list<T>, option<T>, result<T, E>, tuple<T1, T2>
ユーザー定義record, variant, enum, flags
ハンドルresource (own<T>, borrow<T>)

resource

コンポーネント外部のエンティティへの偽造不可能なハンドル。WASI の capability モデルの基盤。

resource blob {
    constructor(init: list<u8>);
    write: func(bytes: list<u8>);      // メソッド (暗黙 self)
    read: func(n: u32) -> list<u8>;
    merge: static func(a: blob, b: blob) -> blob;  // static
}

Canonical ABI

WIT の高水準型と Core Wasm の低水準表現 (i32 等 + 線形メモリ) との変換規則。

主要な型の ABI レイアウト

型alignmentsizeCore Wasm flat
bool11i32
u32 / s3244i32
u64 / s6488i64
stringptr_size2 × ptr_size[ptr, len]
list<T>ptr_size2 × ptr_size[ptr, len]
own<T> / borrow<T>44i32 (ハンドルテーブルインデックス)

flat 化の上限: パラメータ 16個、結果 1個。超過時は cabi_realloc で線形メモリに書き込みポインタのみ渡す。

WASI 0.3 での拡張

追加型説明
stream<T>ジェネリック非同期ストリーム (0.2 の u8 のみから進化)
future<T>ジェネリック Future (0.2 では Resource パターンで模倣)
error-contextコンポーネント境界を跨ぐ構造化エラー

WIT 関数に async キーワードを付与可能に。

Share-Nothing Linking

コンポーネントはメモリを export できない。各コンポーネントインスタンスは独立した線形メモリを持ち、データ交換は Canonical ABI を通じた値のコピーのみ。

利点:

コンポーネントの合成

WAC (WebAssembly Composition)

# plug: 主コンポーネントの未解決 import を依存の export で充足
wac plug calculator.wasm --plug adder.wasm -o composed.wasm

# WAC 言語による高度な合成
wac compose --dep docs:adder=adder.wasm -o final.wasm composition.wac

wasm-tools

wasm-tools component wit component.wasm    # WIT を検査
wasm-tools component new guest.wasm -o component.wasm  # Core → Component

コンポーネントの配布

OCI レジストリ (ghcr.io, DockerHub) で OCI Artifacts として配布:

wkg oci push ghcr.io/user/component:0.1.0 component.wasm
wkg oci pull ghcr.io/user/component:0.1.0

ツールチェーン

言語ツール成熟度
Rustcargo-component, wit-bindgen最も成熟。First-class
JavaScriptjco 1.0, ComponentizeJS安定
Pythoncomponentize-py機能するが成熟途上
C#componentize-dotnetプレビュー (Windows のみ)
GoTinyGo + wit-bindgen-go標準 Go は未対応
Javaなし公式ターゲットなし

Rust での実践

// wit/world.wit:
// package docs:adder@0.1.0;
// interface add { add: func(x: u32, y: u32) -> u32; }
// world adder { export add; }

mod bindings {
    wit_bindgen::generate!({
        path: "wit/world.wit",
    });
    use super::AdderComponent;
    export!(AdderComponent);
}

struct AdderComponent;

impl bindings::exports::docs::adder::add::Guest for AdderComponent {
    fn add(x: u32, y: u32) -> u32 {
        x + y
    }
}
cargo build --target=wasm32-wasip2 --release
# → ~16KB の Component

ユースケース

分野例
プラグインシステムFigma, Shopify Functions, Envoy Proxy, Zed Editor
Edge ComputingFastly Compute, Fermyon Spin (Akamai), Cloudflare Workers
多言語ライブラリ共有Rust ロジックを JS/Python/Go/C# から WIT 経由で呼び出し
AI 推論Cloudflare が Llama-3-8b を 330拠点に展開

現在の状態と課題

項目状態
Wasmtime完全対応 (リファレンス実装)
ブラウザ未対応。jco トランスパイルが必要
W3C 標準化提案段階。WASI 1.0 後に正式フェーズ進行予定
スレッド未対応 (WASI 0.3 ポイントリリースで追加予定)

課題:

押さえどころ(カード化候補)

関連

Graph