spinny:~/writing $ less webassembly-wasm-complete-guide.md
12WebAssembly(WASM)は、もともとブラウザでC++を実行するための技術として始まりました。2026年の現在、ブラウザ、サーバー、エッジネットワーク、組み込みデバイスなど、あらゆる環境で動作し、Web上で最も高負荷なアプリケーションを支えています。Figmaのレンダリングエンジン、Web版Adobe Photoshop、Google Meetの映像処理、そしてCloudflareのエッジコンピューティングプラットフォームは、すべてWebAssembly上で動作しています。34Chrome Platform Statusによると、2026年初頭時点でWASMはChromeのページ読み込みの約5.5%を占めており、前年の4.5%から増加しています。WASM 3.0がW3C標準となり、WASIが1.0に向けて成熟する中、エコシステムは転換点を迎えています。56このガイドでは、WebAssemblyで開発を始めるために必要な知識をすべて解説します。78## WebAssemblyとは何か?910WebAssemblyは、コンパイルターゲットとして設計されたバイナリ命令フォーマットです。高水準言語(Rust、C、C++、Go、Kotlin)でコードを書き、`.wasm`にコンパイルし、WASMランタイムを持つ任意の環境 - ブラウザ、Node.js、Cloudflare Workers、Wasmtime、Wasmer - で実行できます。1112```mermaid13graph LR14 Rust[Rust / C / C++] --> Compiler[Compiler]15 Compiler --> WASM[.wasm Binary]16 WASM --> Browser[Browser V8/SpiderMonkey]17 WASM --> Server[Server Wasmtime]18 WASM --> Edge[Edge Cloudflare Workers]19 WASM --> Embedded[Embedded WAMR]20```2122### 動作の仕組み2324WASMは**スタックベースの仮想マシン**です。関数はオペランドスタック上で値をプッシュ・ポップします。ホストランタイム(ChromeのV8、FirefoxのSpiderMonkey)がWASMバイトコードをネイティブマシンコードにJITコンパイルするため、ネイティブに近い性能を発揮します。2526主な特徴:2728- **サンドボックス実行**: WASMモジュールはホストが明示的に許可したリソースにのみアクセスできます。許可されない限り、ファイルシステム、ネットワーク、OSへのアクセスはありません。これはネイティブコードとは根本的に異なる点です。29- **線形メモリ**: WASMとホスト間で共有される単一の連続した`ArrayBuffer`です。複雑なデータ(文字列、構造体)はメモリに書き込んでポインタを共有することで受け渡します。30- **型の制限**: WASMがネイティブにサポートするのは`i32`、`i64`、`f32`、`f64`の4つの型のみです。それ以外のもの(文字列、配列、オブジェクト)は線形メモリまたはComponent Modelを通じたエンコーディングが必要です。31- **ポータブル**: 同じ`.wasm`バイナリが、再コンパイルなしにWASMランタイムを持つ任意のプラットフォームで動作します。3233### WASM vs JavaScript3435WASMはJavaScriptを置き換えるものではありません。JavaScriptを補完するものです。3637| 項目 | JavaScript | WebAssembly |38|--------|-----------|-------------|39| **パース** | 実行時にパース+コンパイル | プリコンパイル済みバイナリ、デコードのみ |40| **実行速度** | JIT最適化、変動あり | ネイティブに近い、安定 |41| **起動** | 小さなスクリプトでは高速 | 高速デコード、予測可能 |42| **DOMアクセス** | 直接 | 間接(JSグルーコード経由) |43| **最適な用途** | UI、DOM操作、イベント処理 | CPU集約型の計算処理 |44| **ガベージコレクション** | 組み込み | WasmGC(新)、または手動 |4546UIやDOM操作にはJavaScriptを使いましょう。画像処理、動画エンコーディング、物理シミュレーション、暗号処理、データパースなどの重い計算にはWASMを使いましょう。4748## WASM 3.0: 新機能4950WebAssembly 3.0は2025年9月にW3C標準となり、数年にわたって開発されてきた9つの機能を標準化しました。5152| 機能 | 実現すること |53|---------|----------------|54| **WasmGC** | WASMにおけるネイティブガベージコレクション。マネージド言語(Java、Kotlin、Dart)が独自のGCランタイムを同梱せずにWASMにコンパイルできます。Chrome 119以降、Firefox 120以降、Safari 18.2以降でサポート。 |55| **Exception Handling** | WASMにおけるネイティブ`try`/`catch`。以前は、例外処理にJavaScriptへの高コストなラウンドトリップが必要でした。 |56| **Tail Calls** | スタックオーバーフローなしの効率的な再帰を実現。関数型言語にとって重要です。 |57| **Relaxed SIMD** | 並列データ処理のための128ビットベクトル命令。ハードウェア固有の最適化を可能にします。 |58| **Memory64** | 4GBの線形メモリ制限を突破。大規模データ処理に必要です。 |59| **Multi-memory** | 1つのモジュール内に複数の独立したメモリ領域。 |6061最もインパクトが大きいのは**WasmGC**です。これ以前は、JavaやKotlinをWASMにコンパイルするとガベージコレクタ全体をバイナリの一部として同梱する必要があり、ファイルサイズが肥大化していました。現在はブラウザ自体のGCがJavaScriptと同様にWASMモジュールのメモリ管理を行います。6263## WASI: ブラウザを超えたWebAssembly6465ブラウザにおけるWASMは強力ですが、WASMをユニバーサルランタイムにしているのは**WASI(WebAssembly System Interface)**です。WASIはシステムリソース - ファイル、ネットワーク、クロック、乱数 - への標準化されたインターフェースを提供し、WASMモジュールをブラウザ外で実行することを可能にします。6667```mermaid68graph TD69 subgraph "Browser"70 B[WASM Module] --> Web[Web APIs\nDOM, Fetch, Canvas]71 end7273 subgraph "Server / Edge / Embedded"74 S[WASM Module] --> WASI[WASI Interfaces]75 WASI --> FS[wasi:filesystem]76 WASI --> Net[wasi:sockets]77 WASI --> HTTP[wasi:http]78 WASI --> Clock[wasi:clocks]79 WASI --> Rand[wasi:random]80 end81```8283WASI Preview 2(現在の安定リリース)は以下のインターフェースを定義しています:8485- `wasi:filesystem` - ケイパビリティハンドル(従来のファイルディスクリプタではなく)によるファイル操作86- `wasi:sockets` - TCP/UDPネットワーキング87- `wasi:http` - HTTPリクエスト/レスポンス処理88- `wasi:clocks` - ウォールクロック、モノトニッククロック89- `wasi:random` - 暗号学的乱数90- `wasi:cli` - コマンドライン引数、環境変数、標準入出力9192重要な原則は**ケイパビリティベースのセキュリティ**です。WASMモジュールは、ホストが特定のディレクトリへのハンドルを明示的に付与しない限り、ファイルシステムにアクセスできません。これにより、WASIはネイティブ実行ファイルの実行よりも根本的に安全になります。9394### WASI 1.0への道9596WASI 0.3.0(async/並行処理プリミティブの追加)は2026年に予定されており、その後にWASI 1.0が続きます。主な追加機能は、ゼロコピーストリーミングI/Oを備えた言語統合型の非同期処理です。9798## Component Model99100コアWASMモジュールは数値しか交換できません。**Component Model**は、WASMの上にリッチな型システムとコンポーザビリティレイヤーを追加することで、この制限を解決します。101102### WIT (WebAssembly Interface Types)103104WITは、コンポーネントがインポートとエクスポートをリッチな型 - 文字列、レコード、リスト、バリアント、列挙型 - で宣言できるインターフェース定義言語です。`i32`や`f64`だけではありません。105106```wit107// calculator.wit108package myorg:calculator@1.0.0;109110interface operations {111 record calculation {112 expression: string,113 result: f64,114 timestamp: u64,115 }116117 add: func(a: f64, b: f64) -> f64;118 multiply: func(a: f64, b: f64) -> f64;119 history: func() -> list<calculation>;120}121122world calculator {123 export operations;124}125```126127`wit-bindgen`のようなツールチェーンがWITファイルから言語固有のバインディングを生成します。RustコンポーネントとPythonコンポーネントが、相手の実装言語を知ることなく、WITコントラクトを通じて文字列、レコード、リストを交換できます。128129## Rustで最初のWASMモジュールを構築する130131Rustは最も成熟したWASMツールを持っています。実用的な例を作りましょう。ブラウザで動作する画像処理モジュールです。132133### セットアップ134135```bash136# Install the WASM target for Rust137rustup target add wasm32-unknown-unknown138139# Install wasm-pack (builds Rust to WASM + generates JS bindings)140cargo install wasm-pack141142# Create a new library project143cargo new --lib image-processor144cd image-processor145```146147### Cargo.tomlの設定148149```toml150[package]151name = "image-processor"152version = "0.1.0"153edition = "2021"154155[lib]156crate-type = ["cdylib"]157158[dependencies]159wasm-bindgen = "0.2"160```161162### Rustコードの作成163164```rust165// src/lib.rs166use wasm_bindgen::prelude::*;167168/// Convert an image buffer to grayscale.169/// Input: RGBA pixel data as a flat u8 array (4 bytes per pixel).170/// Output: Modified in place for zero-copy performance.171#[wasm_bindgen]172pub fn grayscale(pixels: &mut [u8]) {173 for chunk in pixels.chunks_exact_mut(4) {174 let r = chunk[0] as f32;175 let g = chunk[1] as f32;176 let b = chunk[2] as f32;177 // ITU-R BT.709 luminance coefficients178 let gray = (0.2126 * r + 0.7152 * g + 0.0722 * b) as u8;179 chunk[0] = gray;180 chunk[1] = gray;181 chunk[2] = gray;182 // chunk[3] is alpha, leave unchanged183 }184}185186/// Adjust brightness of an image.187/// factor > 1.0 brightens, < 1.0 darkens.188#[wasm_bindgen]189pub fn adjust_brightness(pixels: &mut [u8], factor: f32) {190 for chunk in pixels.chunks_exact_mut(4) {191 chunk[0] = ((chunk[0] as f32 * factor).min(255.0)) as u8;192 chunk[1] = ((chunk[1] as f32 * factor).min(255.0)) as u8;193 chunk[2] = ((chunk[2] as f32 * factor).min(255.0)) as u8;194 }195}196197/// Invert all colors in the image.198#[wasm_bindgen]199pub fn invert(pixels: &mut [u8]) {200 for chunk in pixels.chunks_exact_mut(4) {201 chunk[0] = 255 - chunk[0];202 chunk[1] = 255 - chunk[1];203 chunk[2] = 255 - chunk[2];204 }205}206207/// Calculate the average brightness of an image (0-255).208#[wasm_bindgen]209pub fn average_brightness(pixels: &[u8]) -> f32 {210 let mut total: f64 = 0.0;211 let pixel_count = pixels.len() / 4;212 for chunk in pixels.chunks_exact(4) {213 let luminance = 0.2126 * chunk[0] as f64214 + 0.7152 * chunk[1] as f64215 + 0.0722 * chunk[2] as f64;216 total += luminance;217 }218 (total / pixel_count as f64) as f32219}220```221222### ビルド223224```bash225wasm-pack build --target web226```227228これにより`pkg/`ディレクトリが生成され、以下が含まれます:229- `image_processor_bg.wasm` - コンパイル済みWASMバイナリ230- `image_processor.js` - TypeScript型定義付きJavaScriptグルーコード231- `package.json` - npmに公開可能な状態232233### JavaScriptでの使用234235```html236<!DOCTYPE html>237<html>238<head><title>WASM Image Processor</title></head>239<body>240 <canvas id="canvas" width="800" height="600"></canvas>241 <button onclick="applyGrayscale()">Grayscale</button>242 <button onclick="applyBrightness()">Brighten</button>243 <button onclick="applyInvert()">Invert</button>244245 <script type="module">246 import init, { grayscale, adjust_brightness, invert } from "./pkg/image_processor.js";247248 let ctx;249 let imageData;250251 async function setup() {252 await init();253 const canvas = document.getElementById("canvas");254 ctx = canvas.getContext("2d");255256 // Load an image onto the canvas257 const img = new Image();258 img.onload = () => {259 ctx.drawImage(img, 0, 0);260 imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);261 };262 img.src = "photo.jpg";263 }264265 window.applyGrayscale = () => {266 grayscale(imageData.data);267 ctx.putImageData(imageData, 0, 0);268 };269270 window.applyBrightness = () => {271 adjust_brightness(imageData.data, 1.3);272 ctx.putImageData(imageData, 0, 0);273 };274275 window.applyInvert = () => {276 invert(imageData.data);277 ctx.putImageData(imageData, 0, 0);278 };279280 setup();281 </script>282</body>283</html>284```285286重要なポイント:`imageData.data`は`ArrayBuffer`に裏付けられた`Uint8ClampedArray`です。WASMに渡されるとき、同じメモリを共有します - コピーは発生しません。Rust関数がピクセルをインプレースで変更し、JavaScript側は即座にその変更を確認できます。287288## 低レベル: 手動WASMインスタンス化289290`wasm-bindgen`を使いたくない場合は、WASMモジュールを直接インスタンス化できます:291292```javascript293const response = await fetch("calculator.wasm");294const { instance } = await WebAssembly.instantiateStreaming(response, {295 env: {296 // Functions the WASM module can call297 log_result: (value) => console.log("Result:", value),298 },299});300301// Call exported functions302const { add, multiply } = instance.exports;303console.log(add(5, 3)); // 8304console.log(multiply(4, 7)); // 28305```306307これは最小限のオーバーヘッドで、リッチな型の相互運用が不要な場合に有用です。308309## パフォーマンス: WASM vs JavaScript310311実際のベンチマークでは、CPU集約型タスクで大幅な高速化が示されています:312313| タスク | JavaScript | WASM | 高速化 |314|------|-----------|------|---------|315| 4K画像処理 | 180ms | 8ms(SIMD使用) | 22倍 |316| 画像リサイズ(4K) | 250ms | 45ms | 5.5倍 |317| 物理シミュレーション(1万エンティティ) | フレーム落ち | スムーズな60fps | 約10倍 |318| JSONパース(大規模ペイロード) | 12ms | 3ms | 4倍 |319| 暗号学的ハッシュ | 45ms | 6ms | 7.5倍 |320321WASMはネイティブコード速度の約95%で動作します。最大のメリットは以下の点から生まれます:322- 予測可能なパフォーマンス(JITウォームアップなし、GCポーズなし)323- 並列データ処理のためのSIMD命令324- ガベージコレクタの干渉なしの直接メモリアクセス325326WASMが速くない場面:DOM操作、小さな計算、I/Oバウンドのタスク。JavaScriptはこれらに対してすでに最適化されています。327328## プロダクション事例329330### Figma: リアルタイムベクターレンダリング331332Figmaのコアレンダリングエンジンは、C++をWASMにコンパイルしたものです。すべてのシェイプ、グラデーション、エフェクトがWASMで計算され、Canvas要素に描画されます。これにより、Figmaはブラウザ上で数千のレイヤーを持つ複雑なデザインを60fpsで処理できます - 純粋なJavaScriptでは不可能なパフォーマンスです。333334### Web版Adobe Photoshop335336AdobeはRustを使ってPhotoshopの主要なフィルターやツールをWASMに移植しました。ベンチマークによると、WASM SIMDによる4K画像処理は22msで、JavaScriptの180msと比較して8倍の改善です - これによりリアルタイムフィルタープレビューが可能になりました。337338### Cloudflare Workers339340Cloudflareは330以上のエッジロケーションにわたるV8アイソレートでWASMモジュールを実行しています。コールドスタートは1-5ms(コンテナベースのサーバーレスの100-500msと比較して)です。2026年2月には、WASMを使用してエッジネットワーク全体にLlama-3-8bの推論をデプロイしました。341342### Google Meet343344Google Meetの背景ぼかしやバーチャル背景は、リアルタイム映像処理にSIMDを使用したWASMを活用しています。WASMモジュールは各ビデオフレームを30fpsのスムーズな映像を維持できる速度で処理します。345346## ブラウザサポート(2026年)347348| 機能 | Chrome | Firefox | Safari | Edge |349|---------|--------|---------|--------|------|350| コアWASM | 完全 | 完全 | 完全 | 完全 |351| Threads | 対応 | 対応 | 対応 | 対応 |352| SIMD(128ビット) | 対応 | 対応 | 対応 | 対応 |353| WasmGC | 119以降 | 120以降 | 18.2以降 | 対応 |354| Exception Handling | 対応 | 対応 | 対応 | 対応 |355| Memory64 | 対応 | 対応 | 部分的 | 対応 |356357すべての主要ブラウザがWASMを完全にサポートしています。新しい機能(WasmGC、Exception Handling)は幅広く利用可能になっています。358359## ツールリファレンス360361| ツール | 用途 | インストール |362|------|---------|---------|363| **wasm-pack** | RustからWASMへのビルド、npmパッケージ生成 | `cargo install wasm-pack` |364| **wasm-bindgen** | Rust/JS相互運用バインディング(wasm-packが使用) | Cargo.tomlの依存関係 |365| **wasm-opt** | バイナリサイズ最適化(50%以上の削減) | Binaryenの一部: `brew install binaryen` |366| **wit-bindgen** | WITファイルからバインディング生成 | `cargo install wit-bindgen-cli` |367| **Wasmtime** | サーバーサイドWASMランタイム(WASIリファレンス実装) | `brew install wasmtime` |368| **Wasmer** | WASIサポート付きの代替WASMランタイム | `curl https://get.wasmer.io -sSfL \| sh` |369| **wasm-feature-detect** | ランタイムブラウザ機能検出 | `npm install wasm-feature-detect` |370371### バイナリサイズの最適化372373WASMバイナリは大きくなることがあります。サイズを縮小する方法は以下の通りです:374375```toml376# Cargo.toml377[profile.release]378opt-level = "z" # Optimize for size379lto = true # Link-time optimization380codegen-units = 1 # Better optimization, slower compile381strip = true # Strip debug symbols382```383384```bash385# Build in release mode386wasm-pack build --release --target web387388# Further optimize with wasm-opt389wasm-opt -Oz pkg/image_processor_bg.wasm -o pkg/image_processor_bg.wasm390```391392一般的なRust WASMモジュールは、これらの最適化により500KBから50KB未満にまで縮小されます。393394## 始めるためのロードマップ395396```mermaid397flowchart TD398 A[Week 1: Basics] --> B[Week 2: Real Project]399 B --> C[Week 3: WASI and Server-side]400 C --> D[Month 2+: Production]401402 A --> A1[Install Rust + wasm-pack]403 A --> A2[Build hello-world WASM module]404 A --> A3[Call WASM functions from JavaScript]405406 B --> B1[Build image processor or game physics]407 B --> B2[Use wasm-bindgen for rich types]408 B --> B3[Benchmark against pure JS]409410 C --> C1[Run WASM with Wasmtime]411 C --> C2[Explore WASI interfaces]412 C --> C3[Try Component Model with WIT]413414 D --> D1[Optimize binary size]415 D --> D2[Use SIMD for parallelism]416 D --> D3[Deploy to Cloudflare Workers or browser]417```418419## まとめ420421WebAssemblyはもはや実験的な技術ではありません。Web上で最も高負荷なアプリケーションに使われているプロダクション技術です。ネイティブに近いパフォーマンス、サンドボックスによるセキュリティ、ユニバーサルなポータビリティ - この3つすべてを提供するコンパイルターゲットは他にありません。422423アプリケーション全体をWASMで書き直す必要はありません。まずは1つのCPU集約型関数 - 画像フィルター、データパーサー、物理計算 - をWASMにコンパイルし、JavaScriptから呼び出してください。その違いを測定し、WASMが他のどこで役立つかを判断しましょう。424425ツールは成熟し、ブラウザサポートはユニバーサルで、エコシステムは成長を続けています。Rustを書いているなら、ブラウザまでたった1つのコマンドです。426427> **始めるためのチェックリスト:**428>429> - [x] Rustとwasm-packのインストール完了430> - [x] 最初のWASMモジュールをビルドしてブラウザで実行431> - [x] JavaScriptとの相互運用が動作(JSからWASMを呼び出し)432> - [x] サイズ最適化を適用したリリースビルド433> - [x] 純粋なJavaScript実装との性能ベンチマーク434> - [x] サーバーサイド用途のWasmtimeでWASIを検証435
:Web開発者のためのWebAssembly - ゼロからプロダクションまでlines 1-435 (END) — press q to close