⚙️

WebAssembly(WASM)はどう動くのか?

C++/Rust/Zigコードをブラウザでネイティブ速度で実行

WebAssembly(WASM)はC++、Rust、Zigなどの静的型付け言語で書かれたコードをブラウザでネイティブに近い速度で実行するバイトコードフォーマットです。

構造ダイアグラム

📝
ソースコード
C / C++ Rust Zig Go (tinygo)
① コンパイル Emscripten / wasm-pack / zig build
📦
npmパッケージ
.wasm(バイトコード) JS/TSラッパー(glue) TypeScript型
② バンドル Vite / webpack
🌐
ブラウザ
WASM Runtime
WebAssembly.compile() WebAssembly.instantiate() JS ↔ WASM呼び出し
WASM配信方式:
A 別途.wasmファイル → fetch()でロード → キャッシュ可能
B base64インライン → JSバンドルに内蔵 → 追加リクエストなし(ghostty-web方式)
ポイント
  • JavaScriptはWASMにコンパイル不可 — WASMは静的型付け言語専用のコンパイルターゲット
  • WASMはDOMに直接アクセス不可 — JSラッパー(glue code)がブリッジ役
  • ブラウザのサンドボックス内で実行 — ネイティブアプリと同一のセキュリティ
  • 実例: Figma(C++)、FFmpeg.wasm(C)、Ghostty Web(Zig)、Photoshop(C++)

動作フロー

1

ソースコード記述(C++, Rust, Zigなどの静的型付け言語)

2

言語別WASMコンパイラで.wasmバイトコード生成(Emscripten, wasm-pack, zig buildなど)

3

JS/TSラッパー(glue code)作成 — WASM関数をJS APIとして公開、Web APIブリッジ

4

npmパッケージとして配布(例: npm install ghostty-web)。WASMはbase64インラインまたは別.wasmファイルでバンドル

5

フロントエンドビルドツール(Vite, webpack)がパッケージをバンドル。dynamic import()でWASMモジュール読み込み

6

ブラウザがWebAssembly.compile() → instantiate()でバイトコードをコンパイルしインスタンス生成

7

JSからWASM関数呼び出し ↔ WASMからJSコールバック呼び出し — 双方向通信で連携

メリット

  • ネイティブに近い実行速度(JS比10〜100倍高速な演算)
  • C++/Rustなど既存コードベース再利用(30年前のC++コードもwebで実行)
  • サンドボックス実行(ブラウザのセキュリティモデルがそのまま適用)
  • 言語非依存(コンパイルさえできればどの言語でもOK)
  • サーバー負荷軽減(重い演算をクライアント側で処理)

デメリット

  • DOM/Web API直接アクセス不可 — 必ずJS glue code経由
  • ビルド環境が複雑(Emscripten/wasm-packインストール、クロスコンパイル)
  • 初期ロード時間(.wasmダウンロード + コンパイルオーバーヘッド)
  • デバッグが困難(ソースマップ未成熟、console.log不可)
  • メモリ管理が手動(GCなし)、JS↔WASMデータ交換にシリアライゼーションコスト

ユースケース

Figma(C++ 2Dレンダリングエンジンをwebでネイティブ速度で) FFmpeg.wasm(サーバー不要でブラウザ上で動画変換) Ghostty Web(Zigターミナルパーサーをwebターミナルで使用) Google Earth Web(C++ 3D地図レンダリング) AutoCAD Web(C++ CADエンジン30年分のコード再利用) Photoshop Web(C++画像処理エンジン)