WebAssembly 2.0の全貌 - GC統合とコンポーネントモデルで変わるWeb開発

2025.12.02

WebAssembly(Wasm)は2017年のリリース以来、Webのパフォーマンス革命を牽引してきました。そして2024年から2025年にかけて、WebAssembly 2.0と呼ばれる一連の新機能が主要ブラウザで利用可能になりました。本記事では、開発者が知っておくべきWebAssembly 2.0の革新的な機能と、実際の活用方法を解説します。

WebAssembly 2.0とは

WebAssembly 2.0は単一のリリースではなく、以下の主要な仕様拡張の総称です。

機能ステータス主な用途
GC(ガベージコレクション)Phase 4 完了高級言語のネイティブサポート
コンポーネントモデルPhase 3モジュール間連携・言語間相互運用
WASI Preview 2安定版サーバーサイド・エッジ実行
Exception HandlingPhase 4 完了try-catch構文のネイティブサポート
Tail CallPhase 4 完了関数型言語の最適化

ガベージコレクション(WasmGC)

なぜGC統合が重要なのか

従来のWebAssemblyは、線形メモリ上で手動メモリ管理を行う必要がありました。これは、C/C++やRustには適していましたが、Java、Kotlin、Dart、Pythonなどの高級言語では、独自のGCランタイムをWasmにバンドルする必要がありました。

flowchart TB
    subgraph Before["従来の問題"]
        App1["Kotlin/Wasm アプリケーション"]
        GC1["Kotlin GCランタイム(〜500KB追加)<br/>← 各言語ごとにGCを持ち込む"]
        Mem1["WebAssembly 線形メモリ"]
        App1 --> GC1 --> Mem1
    end

    subgraph After["WasmGC後"]
        App2["Kotlin/Wasm アプリケーション"]
        GC2["ブラウザ内蔵GC(V8/SpiderMonkey)<br/>← ブラウザのGCを直接利用"]
        App2 --> GC2
    end

WasmGCの実際の効果

Google Sheetsのチームが公開したベンチマークによると、WasmGCへの移行で以下の改善が達成されました。

  • バイナリサイズ: 従来比で約50%削減
  • 起動時間: 2倍以上高速化
  • メモリ使用量: ピーク時で30-40%削減

対応言語とコンパイラ

// WasmGC対応言語の一覧(2025年1月時点)
const wasmGCLanguages = {
  production: [
    "Kotlin/Wasm",      // JetBrains公式サポート
    "Dart/Flutter",     // Google公式、Flutter Web
    "Java (TeaVM)",     // TeaVM 0.10+
  ],
  experimental: [
    "OCaml",            // wasocaml
    "Scheme",           // Hoot
    "Go",               // go-wasm(実験的)
  ],
  planned: [
    "Python",           // Pyodide後継
    "Ruby",             // 検討中
  ]
};

コンポーネントモデル

言語間相互運用の革命

コンポーネントモデルは、異なる言語で書かれたWasmモジュールを、型安全に連携させる仕組みです。

flowchart TB
    subgraph Component["WebAssembly Component"]
        subgraph Modules["Modules"]
            Rust["Rust Module<br/>(画像処理)"]
            Python["Python Module<br/>(ML推論)"]
            JS["JS Module<br/>(UI)"]
        end
        WIT["WIT (WebAssembly Interface Types)<br/>型定義・インターフェース"]

        Rust --> WIT
        Python --> WIT
        JS --> WIT
    end

WIT(WebAssembly Interface Types)

WITは、コンポーネント間のインターフェースを定義する言語です。

// image-processor.wit
package myapp:image-processor@1.0.0;

interface image-ops {
    record image {
        width: u32,
        height: u32,
        data: list,
    }

    record resize-options {
        target-width: u32,
        target-height: u32,
        quality: option,
    }

    resize: func(img: image, opts: resize-options) -> image;
    apply-filter: func(img: image, filter-name: string) -> image;
}

world image-processor {
    export image-ops;
}

実践: Rustコンポーネントの作成

// Cargo.toml
// [dependencies]
// wit-bindgen = "0.25"

use wit_bindgen::generate;

generate!({
    world: "image-processor",
    exports: {
        "myapp:image-processor/image-ops": ImageProcessor,
    }
});

struct ImageProcessor;

impl exports::myapp::image_processor::image_ops::Guest for ImageProcessor {
    fn resize(img: Image, opts: ResizeOptions) -> Image {
        // 高性能な画像リサイズ処理
        let resized = image::imageops::resize(
            &img.to_dynamic_image(),
            opts.target_width,
            opts.target_height,
            image::imageops::FilterType::Lanczos3,
        );
        Image::from_dynamic_image(resized)
    }

    fn apply_filter(img: Image, filter_name: String) -> Image {
        match filter_name.as_str() {
            "grayscale" => img.grayscale(),
            "blur" => img.blur(2.0),
            _ => img,
        }
    }
}

WASI Preview 2

サーバーサイドWebAssemblyの標準化

WASI(WebAssembly System Interface)Preview 2は、ブラウザ外でのWasm実行環境を標準化します。

WASI Preview 2 の主要インターフェース:
├── wasi:io          # ストリーム・ポーリング
├── wasi:clocks      # 時刻・タイマー
├── wasi:random      # 乱数生成
├── wasi:filesystem  # ファイルシステムアクセス
├── wasi:sockets     # TCP/UDPソケット
├── wasi:http        # HTTPクライアント/サーバー
└── wasi:cli         # コマンドライン引数・環境変数

エッジコンピューティングでの活用

Cloudflare Workers、Fastly Compute、Vercel Edgeなど、主要なエッジプラットフォームがWASIをサポートしています。

// WASI HTTP Handler の例(Rust)
use wasi::http::types::{IncomingRequest, ResponseOutparam};

#[export_name = "wasi:http/incoming-handler@0.2.0#handle"]
pub fn handle(request: IncomingRequest, response_out: ResponseOutparam) {
    let path = request.path_with_query().unwrap_or_default();

    let (status, body) = match path.as_str() {
        "/api/hello" => (200, "Hello from WASI!"),
        "/api/time" => {
            let now = wasi::clocks::wall_clock::now();
            (200, format!("Current time: {:?}", now))
        }
        _ => (404, "Not Found"),
    };

    let response = OutgoingResponse::new(status);
    response.body().unwrap().write_all(body.as_bytes());
    ResponseOutparam::set(response_out, Ok(response));
}

Exception Handling

ネイティブ例外サポート

従来のWasmでは、例外処理をJavaScriptとの境界で行うか、エラーコードベースの処理が必要でした。Exception Handling提案により、言語ネイティブの例外機構がサポートされます。

// C++での例外処理(Emscripten)
#include <emscripten.h>
#include <stdexcept>

EMSCRIPTEN_KEEPALIVE
int divide(int a, int b) {
    if (b == 0) {
        throw std::invalid_argument("Division by zero");
    }
    return a / b;
}
// JavaScript側での呼び出し
try {
    const result = Module._divide(10, 0);
} catch (e) {
    // Wasm例外を直接キャッチ可能に
    console.error("Caught Wasm exception:", e.message);
}

パフォーマンス比較

ベンチマーク結果(2025年1月)

ベンチマークJavaScriptWasm 1.0Wasm 2.0 (GC)
JSON Parse100ms45ms42ms
画像フィルタ850ms120ms115ms
Kotlin Hello World 起動-380ms95ms
Dart アプリ初期化-520ms180ms

注目ポイント: GC統合言語(Kotlin、Dart)では、起動時間が大幅に改善されています。これは、ブラウザ内蔵GCの最適化が適用されるためです。

今すぐ始める

開発環境のセットアップ

# Rust + WebAssembly コンポーネント開発
rustup target add wasm32-wasip2
cargo install cargo-component

# 新規プロジェクト作成
cargo component new my-wasm-component
cd my-wasm-component

# ビルド
cargo component build --release

ブラウザ互換性

機能ChromeFirefoxSafariEdge
WasmGC119+120+18.2+119+
Exception Handling95+100+15.2+95+
Tail Call112+121+-112+
SIMD91+89+16.4+91+

まとめ

WebAssembly 2.0は、Webプラットフォームの可能性を大きく広げる技術革新です。

  • WasmGC: 高級言語のファーストクラスサポート
  • コンポーネントモデル: 言語間相互運用性の実現
  • WASI Preview 2: サーバーサイド/エッジの標準化

これらの機能により、「どの言語でも、どこでも動く」というWebAssemblyのビジョンが現実のものとなりつつあります。今後のWeb開発において、Wasmの重要性はさらに高まることが予想されます。

参考リンク

← 一覧に戻る