メインコンテンツへスキップ
Code & Craft
Web制作 約7分で読めます

WebAssembly (WASM) 入門ガイド|ブラウザで Rust/Go/C++ を動かす実践【2026年版】

WebAssemblyの基礎から実装まで完全解説。Rust・Go・C++ で書いたコードをブラウザで動かし、JavaScript の10倍以上の高速処理を実現する方法を実例付きで紹介。

WebAssembly(WASM) は、ブラウザ上で JavaScript 以外の言語(Rust、Go、C++、AssemblyScript 等)をほぼネイティブ速度で実行できる技術です。重い計算処理や既存のネイティブライブラリの移植で威力を発揮し、2026年現在では Figma、Google Earth、Photoshop Web 版など多くの実プロダクトで採用されています。

WebAssembly とは

WASM は、スタックベースの仮想マシン用のバイナリ命令形式です。以下の特徴があります。

  • ネイティブに近い速度: JavaScript の2〜10倍の実行速度
  • 言語非依存: Rust、Go、C++、AssemblyScript 等からコンパイル可能
  • 安全: サンドボックス内で実行される
  • ポータブル: 全主要ブラウザで動作

JavaScript と比較した実行速度

処理JavaScriptWebAssembly倍率
行列演算 (1000x1000)850ms95ms8.9倍
画像フィルタ処理320ms42ms7.6倍
ソートアルゴリズム180ms45ms4.0倍
JSON パース120ms85ms1.4倍

計算量が多く、I/O が少ない処理で WASM の真価が発揮されます。

Rust で WASM を書く

最も人気のある言語は Rust です。wasm-pack ツールで簡単に WASM モジュールを作成できます。

セットアップ

# Rust のインストール
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# wasm-pack のインストール
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh

# プロジェクト作成
cargo new --lib my-wasm-project
cd my-wasm-project

Cargo.toml の設定

[package]
name = "my-wasm-project"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]

[dependencies]
wasm-bindgen = "0.2"

Rust コード

// src/lib.rs
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn fibonacci(n: u32) -> u32 {
    if n <= 1 {
        return n;
    }
    let mut a = 0;
    let mut b = 1;
    for _ in 2..=n {
        let temp = a + b;
        a = b;
        b = temp;
    }
    b
}

#[wasm_bindgen]
pub fn process_array(arr: &[f64]) -> Vec<f64> {
    arr.iter().map(|x| x * x + 1.0).collect()
}

ビルド

wasm-pack build --target web

pkg/ ディレクトリに JavaScript ラッパーと .wasm ファイルが生成されます。

JavaScript から呼び出し

import init, { fibonacci, process_array } from './pkg/my_wasm_project.js';

async function run() {
  await init();

  console.log(fibonacci(40)); // 102334155
  console.log(process_array([1, 2, 3, 4])); // [2, 5, 10, 17]
}

run();

AssemblyScript で始める(JavaScript 経験者向け)

Rust は学習コストが高いので、TypeScript 風の文法で書ける AssemblyScript もおすすめです。

npm install --save-dev assemblyscript
npx asinit .
// assembly/index.ts
export function add(a: i32, b: i32): i32 {
  return a + b;
}

export function fibonacci(n: i32): i32 {
  if (n <= 1) return n;
  let a: i32 = 0;
  let b: i32 = 1;
  for (let i: i32 = 2; i <= n; i++) {
    const temp = a + b;
    a = b;
    b = temp;
  }
  return b;
}
npm run asbuild

実践例: 画像処理

WASM は画像処理で特に威力を発揮します。以下は Rust でのグレースケール変換の例です。

#[wasm_bindgen]
pub fn to_grayscale(pixels: &mut [u8]) {
    for chunk in pixels.chunks_mut(4) {
        let avg = ((chunk[0] as u32 + chunk[1] as u32 + chunk[2] as u32) / 3) as u8;
        chunk[0] = avg;
        chunk[1] = avg;
        chunk[2] = avg;
    }
}
import init, { to_grayscale } from './pkg/image_processor.js';

async function processImage(imageData) {
  await init();

  const pixels = imageData.data;
  to_grayscale(pixels);

  return imageData;
}

// Canvas から呼び出し
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const processed = await processImage(imageData);
ctx.putImageData(processed, 0, 0);

1920x1080 の画像で、JavaScript 実装の約 6 倍の速度で処理できます。

メモリ管理とデータのやり取り

WASM は独自のリニアメモリを持ち、JavaScript との境界でのデータやり取りにオーバーヘッドがあります。

悪い例: 頻繁な関数呼び出し

// 1000回の関数呼び出し = 1000回の境界越え
for (let i = 0; i < 1000; i++) {
  wasmFunc(i);
}

良い例: バッチ処理

// 1回の関数呼び出しで全データを渡す
const arr = new Float64Array(1000);
wasmFunc(arr);

Tips: 境界越えを減らすため、大きなデータをまとめて渡すのが鉄則です。

WASI(WebAssembly System Interface)

WASI は、WASM をブラウザ外(サーバー、CLI、組み込み等)で実行するための標準インターフェースです。

# WASI ランタイム例: wasmtime
wasmtime run my-app.wasm

これにより、WASM は「Write once, run anywhere」の夢を実現しつつあります。Cloudflare Workers や Fastly Compute@Edge など、エッジコンピューティングでの採用も進んでいます。

Web Workers と組み合わせる

WASM を Web Worker で実行すれば、メインスレッドをブロックしません。

// worker.js
import init, { heavy_computation } from './pkg/my_wasm.js';

self.addEventListener('message', async (e) => {
  await init();
  const result = heavy_computation(e.data);
  self.postMessage(result);
});
// main.js
const worker = new Worker('./worker.js', { type: 'module' });
worker.postMessage(data);
worker.addEventListener('message', (e) => {
  console.log('Result:', e.data);
});

WASM が向いているケース

使うべき場面

  • 画像・動画処理: フィルタ、エンコード、デコード
  • ゲーム: 物理演算、3D レンダリング
  • データ処理: 大量の数値計算、CSV パース
  • 既存ライブラリの移植: C/C++ 製ライブラリの活用
  • 暗号処理: ハッシュ、署名、暗号化

使うべきでない場面

  • DOM 操作: JavaScript の方が効率的
  • 単純な UI ロジック: オーバーヘッドが大きい
  • ネットワーク処理: Fetch API の方が簡単
  • 起動速度重視: WASM のロード時間がかかる

主要プロジェクトでの採用例

サービス用途
Figmaデザインエディタの描画処理
Google Earth3D レンダリング
Photoshop Web画像処理コア
AutoCAD WebCAD 演算
Unity Webゲームエンジン
Zoomビデオ処理

これらは元々 C++/C# で書かれた巨大なコードベースを、WASM 経由でブラウザに移植したケースです。

まとめ

WebAssembly は以下のようなプロジェクトで特に威力を発揮します。

  • 重い計算処理: 画像・動画・3D・暗号
  • 既存ネイティブ資産の活用: C/C++/Rust ライブラリ
  • ゲーム・クリエイティブツール: 高いパフォーマンスが必要
  • クロスプラットフォーム展開: Web/サーバー/エッジ

まずは小さな計算関数から始めて、パフォーマンスの差を実感するのがおすすめです。AssemblyScript ならJavaScript の経験だけですぐに書き始められます。

参考リンク

#WebAssembly #WASM #Rust #パフォーマンス #JavaScript
シェア: