AI

WebAssembly(Wasm)入門ガイド:Wasmtime vs WasmEdge vs Extism でOSSのWasmランタイムを比較

オープンソースラボ編集部2026年6月13日

WebAssembly(Wasm)入門ガイド:Wasmtime vs WasmEdge vs Extism でOSSのWasmランタイムを比較

WebAssembly(Wasm)はブラウザ外でも動作するバイナリ形式の仮想命令セットです。Wasmtime(Bytecode Alliance)・WasmEdge(CNCF)・Extism(プラグインシステム)はWasmをサーバー・エッジ・組み込み環境で実行するOSSランタイムです。「Dockerより軽量で、Native並みに速く、どの言語でもコンパイルできる」という特性から、プラグインシステム・エッジコンピューティング・AI推論に注目が集まっています。

WebAssembly(Wasm)とは

WebAssemblyは当初ブラウザでC/C++コードを高速実行するために設計されましたが、現在は**WASI(WebAssembly System Interface)**によってブラウザ外のサーバー・エッジでも動作します。コンセプトを一言で: 「どこでも動く・安全な・高速なバイナリ形式」

Wasmの特性:

  • ポータビリティ: Rust・C/C++・Go・Python・Kotlin等のコードを.wasmにコンパイルしてどこでも実行
  • サンドボックス: Wasmランタイムは完全なサンドボックスで、システムコールを明示的に許可しない限りOSにアクセスできない
  • 起動速度: Dockerコンテナ起動(数百ms)に対してWasmは1ms以下
  • ファイルサイズ: Dockerイメージ(数十〜数百MB)に対してWasmバイナリは数百KB〜数MB

主要ランタイムの概要

Wasmtime

Bytecode Alliance(Mozilla・Fastly・Intel・Arm等の企業連合)製のWasmランタイムです。GitHubスター15k+。WASIの参照実装であり、Cranelift JITコンパイラで高速実行を実現します。RustのAPIが最も充実しており、安全性・性能・WASI準拠度のバランスが良い。Cloudflare Workers・Fastly Compute(エッジ実行環境)のバックエンドとしても採用されています。

// WasmtimeでWasmモジュールをRustから実行
// Cargo.toml: wasmtime = "26"

use wasmtime::*;
use anyhow::Result;

fn main() -> Result<()> {
    // Wasmtimeエンジンの設定
    let engine = Engine::new(Config::new().debug_info(true))?;
    let store = Store::new(&engine, ());

    // Wasmバイナリをロード(ファイルまたはバイト列)
    let module = Module::from_file(&engine, "plugin.wasm")?;

    // ホスト関数を定義(WasmからRustの関数を呼び出せる)
    let mut linker = Linker::new(&engine);
    linker.func_wrap("env", "log", |msg_ptr: i32, msg_len: i32| {
        println!("Wasm log: ptr={msg_ptr} len={msg_len}");
    })?;

    // Wasmモジュールをインスタンス化
    let instance = linker.instantiate(&mut store, &module)?;

    // Wasmの関数を呼び出す
    let process = instance.get_typed_func::<(i32, i32), i32>(&mut store, "process")?;
    let result = process.call(&mut store, (42, 100))?;
    println!("Result: {result}");

    Ok(())
}
# WasmtimeのPythonバインディングでWasmを実行
# pip install wasmtime

from wasmtime import Store, Module, Instance, Func, FuncType, ValType

store = Store()

# インラインWATコードをコンパイル(テスト用)
module = Module(store.engine, '''
(module
  (func (export "add") (param i32 i32) (result i32)
    local.get 0
    local.get 1
    i32.add)
)
''')

instance = Instance(store, module, [])
add_func = instance.exports(store)["add"]
result = add_func(store, 40, 2)
print(f"40 + 2 = {result}")  # 42

# .wasmファイルを読み込んで実行
with open("my_plugin.wasm", "rb") as f:
    wasm_bytes = f.read()

module = Module(store.engine, wasm_bytes)
instance = Instance(store, module, [])

WasmEdge

CNCF(Cloud Native Computing Foundation)Sandboxプロジェクトのランタイムです。GitHubスター9k+。AI推論(LLM・画像認識)の高速化に特化しており、ONNX・TensorFlow Lite・PyTorch等をWasmから呼び出せます。Kubernetes・コンテナランタイム(containerd/crun)との統合が進んでおり、「DockerコンテナをWasmで置き換える」ユースケースに強い。

# WasmEdgeをインストール
curl -sSf https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install.sh | bash
source ~/.wasmedge/env

# GoのプログラムをWasmにコンパイルしてWasmEdgeで実行
# GOARCH=wasm GOOS=wasip1 go build -o main.wasm .
wasmedge main.wasm

# WasmEdge + WASI-NNでONNXモデルを実行(AI推論)
wasmedge --dir .:.   --env WASMEDGE_PLUGIN_PATH=/usr/local/lib/wasmedge   --nn-preload default:ONNX:CPU:model.onnx   onnx_inference.wasm
// WasmEdgeでHTTPサーバーをWasm内で動かす(actix-web)
// このRustコードをWasmにコンパイルしてWasmEdgeで実行できる
// cargo build --target wasm32-wasi --release

use actix_web::{web, App, HttpServer, HttpResponse};

async fn hello() -> HttpResponse {
    HttpResponse::Ok().body("Hello from WebAssembly!")
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .route("/", web::get().to(hello))
    })
    .bind("0.0.0.0:8080")?
    .run()
    .await
}

Extism

さまざまなWasmランタイム(Wasmtime・WasmEdge等)の上にプラグインシステムを構築するOSSフレームワークです。GitHubスター5k+。Extismの目的は「どんなアプリにも安全なプラグイン機能を追加する」で、プラグインをWasmで実装することでRust・Go・Python・TypeScript等どんな言語でプラグインを書いても安全に実行できます。

// Node.jsアプリにExtismでWasmプラグインシステムを追加
// npm install @extism/extism

import { Plugin } from '@extism/extism';
import { readFileSync } from 'fs';

async function main() {
  // Wasmプラグインをロード(サードパーティが提供するWasmファイル)
  const wasmBytes = readFileSync('./plugin.wasm');

  const plugin = await Plugin.fromBuffer(wasmBytes, {
    useWasi: true,
    // ホスト関数を定義(プラグインからNode.jsの関数を呼び出せる)
    functions: [
      {
        namespace: 'extism:host/user',
        name: 'send_notification',
        signature: { params: ['i64'], results: [] },
        callback: (currentPlugin: any, inputs: any[]) => {
          const message = currentPlugin.read(inputs[0]).text();
          console.log(`Notification: ${message}`);
        },
      },
    ],
  });

  // プラグインの関数を呼び出す
  const result = await plugin.call('process_data', JSON.stringify({
    input: 'Hello from the host!',
    config: { max_length: 100 },
  }));

  console.log('Plugin result:', result.text());
  await plugin.close();
}

main();
// GoでExtismプラグインを実装する(プラグイン側のコード)
// このGoコードをwasm32-wasip1にコンパイルしてホストから呼び出せる
// GOOS=wasip1 GOARCH=wasm go build -o plugin.wasm

package main

import (
    "encoding/json"
    "github.com/extism/go-pdk"
)

type Input struct {
    Input  string `json:"input"`
    Config struct {
        MaxLength int `json:"max_length"`
    } `json:"config"`
}

//go:export process_data
func processData() int32 {
    input := pdk.Input()
    var req Input
    json.Unmarshal(input, &req)

    result := req.Input
    if len(result) > req.Config.MaxLength {
        result = result[:req.Config.MaxLength]
    }

    pdk.OutputString(`{"result":"` + result + `","length":` + fmt.Sprintf("%d", len(result)) + `}`)
    return 0
}

func main() {}

ユースケース別比較表

ユースケースWasmtimeWasmEdgeExtism
サーバーサイドWasm△(ラッパー)
AI推論(LLM/ONNX)
プラグインシステム
エッジコンピューティング
Kubernetes統合
言語サポートRust中心多言語多言語
GitHub Stars15k+9k+5k+

WasmをエッジランタイムとしてKubernetesに統合するパターンはDevOpsカテゴリ/categories/devopsを参照してください。WasmをAI推論バックエンドとして使う実装はLLMツールカテゴリ/categories/llm-toolsにまとめています。

FAQ

Q. WebAssemblyはDockerを置き換えるものですか?

A. 部分的には代替できますが、完全な置き換えではありません。WasmがDockerより優れる点: 起動速度(1ms以下 vs 数百ms)・メモリ効率・強固なサンドボックス・クロスプラットフォーム(1つのwasmファイルがあらゆるOSで動く)。DockerがWasmより優れる点: 任意のOS機能(システムコール)へのアクセス・既存のLinuxアプリをそのままコンテナ化・Dockerエコシステム(Docker Hub・Compose・Kubernetes)。現実的な答え: Wasm はステートレスなビジネスロジック・プラグイン・関数(FaaS)に最適で、データベース・OS依存のシステムソフトウェアにはDockerの方が適しています。「DockerとWasmの共存」(KubernetesでWasmとコンテナを混在させる)が2026年の主流アプローチです。KubernetesはRuntimeClass: wasmtimeでWasmコンテナを実行できます。

Q. RustでWebAssemblyを書くのと、GoでWebAssemblyを書くのではどちらが適していますか?

A. Rustが最適: ①パフォーマンスが最も高い②wasmバイナリが最も小さい(ランタイムなし)③wasm-bindgen・wasm-pack等のエコシステムが最も成熟④セキュリティ(メモリ安全性)。Goが適している場合: ①既存のGoコードベースをWasmに移植したい②チームのRust習熟度が低い③バイナリサイズが多少大きくても構わない。注意: GoのwasipターゲットはGoランタイム込みでWasmサイズが大きくなる(最小でも数MB)。TinyGoを使うと数百KBに削減できます。Python/TypeScript: Pyodide(PythonのWasm版)・AssemblyScript(TypeScript→Wasm)という選択肢もありますが、パフォーマンスや成熟度の面でRust/Goに及びません。

Q. Next.jsアプリからWasmモジュールを呼び出すには?

A. Next.js(Webpack)はWasmのインポートをサポートしています。

// Next.js App RouterでWasmを使う
// app/api/process/route.ts

// Wasm Bindgenで生成したTypeScriptバインディングを使う
// (wasm-pack build --target web でビルド)
import init, { process_text } from '@/wasm/my_module';

let initialized = false;

export async function POST(req: Request) {
  // Wasmを初期化(初回のみ)
  if (!initialized) {
    await init();
    initialized = true;
  }

  const { text } = await req.json();

  // Wasm関数を呼び出す(RustでコンパイルされたWebAssembly)
  const result = process_text(text);

  return Response.json({ result });
}
// next.config.ts でWasmを有効化
const nextConfig = {
  webpack(config) {
    config.experiments = {
      ...config.experiments,
      asyncWebAssembly: true,
    };
    return config;
  },
};
export default nextConfig;

Edge Runtimeでも動作させるにはexport const runtime = 'edge'とWasmをfetch経由でロードする手法を使います。

Q. Extismでサードパーティプラグインを安全にユーザーに配布する方法は?

A. Extismのプラグインはハッシュ(SHA256)で検証できます。

// ユーザーがアップロードしたWasmプラグインを安全に実行
import { Plugin } from '@extism/extism';
import { createHash } from 'crypto';

const TRUSTED_PLUGIN_HASHES = new Set([
  'a3b4c5d6...', // 信頼済みプラグインのSHA256ハッシュ
]);

async function runUserPlugin(wasmBytes: Buffer, input: string) {
  // ハッシュ検証
  const hash = createHash('sha256').update(wasmBytes).digest('hex');
  if (!TRUSTED_PLUGIN_HASHES.has(hash)) {
    throw new Error('Untrusted plugin: hash verification failed');
  }

  const plugin = await Plugin.fromBuffer(wasmBytes, {
    useWasi: true,
    // リソース制限(Wasmのサンドボックスで制限)
    allowedPaths: {},      // ファイルシステムアクセス禁止
    allowedHosts: [],      // ネットワークアクセス禁止
    memoryMax: 10,         // 最大10ページ(640KB)
  });

  const result = await plugin.call('run', input);
  await plugin.close();
  return result.text();
}

まとめ

ユースケース推奨ランタイム
高性能WasmサーバーWasmtime
AI推論・Kubernetes統合WasmEdge
プラグインシステム構築Extism
ブラウザ+サーバー共通Wasmtime(WASI)

関連外部リソース

他の記事も読む

Let's Build Together

OSS導入、自社だけで悩まない。

ツール選定から構築・運用・AI活用まで、オープンソースラボ運営元のClasslessが伴走します。初回のご相談は無料です。