WebAssemblyとは?

WebAssembly(略称:Wasm)は、ブラウザ等の環境で実行できる コンパクトなバイナリ形式(+テキスト表現)です。 JavaScriptと連携しつつ、計算負荷の高い処理をネイティブに近い性能で動かす目的で使われます。

ポイント

  • 速い:バイナリで配布し、実行が効率的
  • 安全:サンドボックスで実行(基本は外に勝手に出られない)
  • 移植性:同じWasmを複数環境(ブラウザ/サーバー)で

誤解されがち

  • Wasmは「JavaScriptを置き換える言語」ではなく、補完する実行形式
  • DOM操作は基本JS側(Wasmは計算や内部処理が得意)
  • 万能最適解ではなく、境界コスト(JS↔Wasm)がある
ワズム(Wasm):WebAssembly の公式略称。読みは「ワズム」。

WebAssemblyで何ができますか?

重い計算

画像処理、音声処理、物理計算、暗号、圧縮、機械学習の推論など。

既存資産の移植

C/C++/Rust等のライブラリをWebへ。例えばエンコーダ/デコーダ類。

サーバー/エッジ

WASI + Wasm runtime(例:Wasmtime)で「小さく安全に」実行。

向いている/向いていない

向いている

  • CPUを使う処理がボトルネック
  • 既存ネイティブ資産をWebへ持っていきたい
  • 安全なプラグイン実行(サンドボックス)が欲しい

向いていない

  • DOMを頻繁に触るUI中心(JS/TSの方が素直)
  • JS↔Wasmを超える呼び出しが大量に発生する設計
  • 小さい処理を無理にWasm化(境界コストで損しがち)

用語整理(Wasm / WAT / WASI)

.wasm

実行されるバイナリ形式。配布に向いていて軽い。

.wat

人間が読めるテキスト表現(デバッグ/学習で便利)。

WASI

WebAssembly System Interface。 ファイル/時刻/乱数/標準入出力など「OSっぽい機能」を、 安全に提供するための標準化API群。 ブラウザ以外(サーバー/エッジ/組み込み)でWasmを動かすときの鍵。

JavaScriptとの連携

Web上のWasmは、基本的に JavaScriptから読み込み関数を呼び出す形になります。 「UIやDOMはJS」「計算コアはWasm」という分担が定番です。

JSでWasmを読み込む最小例
// example.js
// const bytes = await fetch("module.wasm").then(r => r.arrayBuffer());
// const { instance } = await WebAssembly.instantiate(bytes, importObject);
// console.log(instance.exports.add(1, 2));

※ 実運用では instantiateStreaming() や bundler/wasm-pack 等で扱うことが多いです。

データ受け渡しのコツ

  • 数値計算は得意(int/float)
  • 文字列や配列は「メモリ共有(Linear Memory)」経由になりがち → 設計が重要
  • JS↔Wasmの呼び出し回数が多いと遅くなることがある → まとめて処理が鉄則

WasmとJavaの違い

観点 Wasm Java
正体 低レベルのバイナリ実行形式(仮想マシン向けISA) 言語+JVMで動くバイトコード
主戦場 ブラウザ / サーバー / エッジ(WASIなど) サーバー / Android / 業務システム中心
メモリ 基本は線形メモリ(言語側のランタイムで管理) GC中心(JVMのヒープ管理)
目的 多言語のコンパイル先として移植性+安全な実行 Java言語の実行と巨大なエコシステム
UI ブラウザではDOMはJS側が基本 GUIは別技術(JavaFX等)/ Webなら別スタック
ざっくり言うと、Javaは「言語+JVM」、Wasmは「多言語のための実行形式」です。

作り方(ツールチェーン)

代表的なルートだけ、実務でよく使う順に並べます。

Rust → Wasm(定番)

  • wasm-pack / wasm-bindgen でJS連携がやりやすい
  • ビルド成果物をbundlerに載せやすい

C/C++ → Wasm(資産移植)

  • Emscripten が定番(既存C/C++をWebへ)
  • 大きいライブラリ移植向き
Rustでの雰囲気(イメージ)
// lib.rs(イメージ)
// #[wasm_bindgen]
// pub fn add(a: i32, b: i32) -> i32 { a + b }
まずは「Wasmにする理由(ボトルネック)」→「データ境界の設計」→「ツール選定」の順で決めると失敗しにくいです。

代表ユースケース

画像/動画

フィルタ、エンコード/デコード、編集、背景処理など。

ゲーム/シミュ

物理演算、経路探索、AI推論などの重処理を担当。

プラグイン実行

Wasmを「安全な拡張機構」としてホストアプリに埋め込む。

サーバー側(WASI + ランタイム)

ブラウザ以外でも、Wasmランタイム(例:Wasmtime)上で動かし、 必要な権限(ファイル/環境変数など)だけを渡す設計ができます。

できないこと / 注意点

  • DOM直操作が苦手:UIはJS/TS側が基本
  • 境界コスト:JS↔Wasmの呼び出し・データ変換はタダではない
  • デバッグ:慣れるまではJS単体より手間が増える
  • セキュリティ:サンドボックスでも「ホストが許可した機能」は使える → 権限設計が肝
「速いから全部Wasm」は危険。重い部分だけ切り出す方が結果的に速く・保守もしやすいです。

FAQ