Contents
1. 必要ツールのインストール
| ツール | 用途 | 推奨インストールコマンド |
|---|---|---|
| rustup | Rust コンパイラ・標準ライブラリのバージョン管理 | curl https://sh.rustup.rs -sSf \| sh(macOS / Linux)winget install --id=Rustlang.Rustup(Windows) |
wasm‑target (wasm32-unknown-unknown) |
Rust から直接 Wasm バイナリを生成 | rustup target add wasm32-unknown-unknown |
| Node.js (npm / pnpm) | ローカルサーバや npm パッケージの管理 | https://nodejs.org/ からインストーラ取得 (pnpm は npm i -g pnpm) |
| Python | 簡易 HTTP サーバ(標準ライブラリのみで可) | python --version が出れば OK |
| wasm‑pack | Rust → Wasm + JS ラッパーの自動生成ツール | bash\ncargo install wasm-pack\n |
| Trunk | Cargo と連携した開発サーバ・HTML ビルド | cargo install trunk |
| binaryen (wasm‑opt) | リリースビルド時のサイズ最適化 | macOS: brew install binaryenUbuntu: sudo apt-get install binaryenWindows: scoop install binaryen または choco install binaryen |
1‑1. wasm‑pack のインストール手順(抜粋)
|
1 2 3 4 5 6 |
# Cargo がインストール済みであれば以下だけ cargo install wasm-pack # インストールが成功したか確認 wasm-pack --version # → 例: wasm-pack 0.12.1 |
ポイント
cargo installはグローバルにバイナリを配置します。環境変数$HOME/.cargo/binがパスに入っていない場合は手動で追加してください(Windows の場合は「システム環境変数」から)。
1‑2. binaryen / wasm‑opt の Windows インストール例
|
1 2 3 4 5 6 7 |
# Scoop を利用するケース iwr -useb get.scoop.sh | iex scoop install binaryen # Chocolatey を利用するケース choco install binaryen -y |
インストール後は wasm-opt --version でバージョンが表示されれば完了です。
2. プロジェクトの作成と Cargo 設定
2‑1. ライブラリテンプレートの生成
|
1 2 3 |
cargo new --lib hello-wasm cd hello-wasm |
src/lib.rs がエクスポート対象になるので、ここに wasm-bindgen のコードを書きます。
2‑2. Cargo.toml の基本設定
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
[package] name = "hello-wasm" version = "0.1.0" edition = "2021" [lib] crate-type = ["cdylib"] # WebAssembly 用の出力形式 [dependencies] wasm-bindgen = "0.2" # Rust ↔ JavaScript のブリッジ # ビルドサイズを意識した設定(オプション) [profile.release] opt-level = "z" # -Oz と同等、サイズ最適化 |
注意
Trunk でバイナリを直接ビルドさせる場合は[[bin]]セクションは不要です。lib.rsが生成物 (hello_wasm.wasm) の入口になるため、[lib]にだけcrate-type = ["cdylib"]を記述します。
2‑3. Trunk 用メタデータ(任意)
|
1 2 3 4 5 |
# Cargo.toml の末尾に追記 [package.metadata.trunk] dist = "dist" # 出力先ディレクトリ(デフォルトは `dist/`) public_url = "/" # 公開時のベース URL |
この設定があれば、trunk serve 実行時に自動的に index.html がバンドルされます。
3. ビルド手順と選択肢
3‑1. cargo build(低レベルビルド)
|
1 2 |
cargo build --target wasm32-unknown-unknown # デバッグビルド |
生成物は target/wasm32-unknown-unknown/debug/hello_wasm.wasm のみです。
JS ラッパーが必要な場合は別途 wasm-bindgen-cli を呼び出します。
|
1 2 3 |
wasm-bindgen target/wasm32-unknown-unknown/debug/hello_wasm.wasm \ --out-dir pkg --target web |
3‑2. wasm-pack build(推奨フロー)
|
1 2 3 4 |
# 開発中はデバッグビルド、リリース時は --release を付与 wasm-pack build --target web # デフォルトは debug wasm-pack build --release --target web # 本番向け最適化ビルド |
pkg/ ディレクトリに以下が生成されます。
hello_wasm_bg.wasm(実体バイナリ)hello_wasm.js、hello_wasm_bg.js(JS ラッパー).d.tsファイル(TypeScript 用型情報)
3‑3. Trunk を使ったワンコマンド開発サーバ
|
1 2 |
trunk serve --open # 自動リロード付きでブラウザが起動 |
Trunk は内部的に wasm-pack build --release(デフォルトは debug)を呼び出し、生成された Wasm と HTML を同時に配信します。
開発中の推奨パターンは次のとおりです。
| コマンド | 用途 |
|---|---|
cargo build --target wasm32-unknown-unknown |
ビルドだけ確認したいとき |
wasm-pack build |
npm パッケージとして出力したいとき |
trunk serve |
フロントエンド全体をホットリロードで検証したいとき |
4. HTML 側から Wasm を呼び出す例
4‑1. 基本的なインポート(ES モジュール)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>Hello WASM</title> </head> <body> <h1 id="msg">Loading…</h1> <script type="module"> import init, { greet } from "./pkg/hello_wasm.js"; async function main() { await init(); // Wasm のロードとインスタンス化 const txt = greet("Rust"); document.getElementById('msg').textContent = txt; } main().catch(console.error); </script> </body> </html> |
init() が Promise を返すため、await(または .then)でロード完了を待つことが重要です。これにより 未初期化エラー を防げます。
4‑2. エラーハンドリングのベストプラクティス
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import init, { greet } from "./pkg/hello_wasm.js"; (async () => { try { await init(); console.log(greet("Trunk")); } catch (e) { // ネットワーク障害や MIME 設定ミスが原因のことが多い console.error("WASM のロードに失敗しました:", e); document.getElementById('msg').textContent = "ロードエラー"; } })(); |
ブラウザコンソールとネットワークタブで 404 や MIME type エラーが出ていないか確認しましょう。
5. デバッグ・最適化テクニック
5‑1. ソースマップ付きデバッグビルド
|
1 2 |
wasm-pack build --target web --debug # ← sourceMappingURL が生成される |
Chrome DevTools の Sources タブで *.rs ファイルが直接表示され、ステップ実行や変数監視が可能です。
5‑2. panic 時のスタックトレースを有効化
|
1 2 3 |
[dependencies] console_error_panic_hook = "0.1" |
lib.rs の先頭に以下を追加すると、panic が発生した際に JavaScript コンソールへ Rust のスタックトレースが出力されます。
|
1 2 3 4 5 6 7 8 9 |
#[cfg(feature = "console_error_panic_hook")] extern crate console_error_panic_hook; use std::panic; pub fn set_panic_hook() { #[cfg(feature = "console_error_panic_hook")] panic::set_hook(Box::new(console_error_panic_hook::hook)); } |
wasm-pack build --release --features console_error_panic_hook で有効化できます。
5‑3. wasm-opt(binaryen)によるサイズ圧縮
|
1 2 3 |
# リリースビルド後に実行 wasm-opt -Oz -o pkg/hello_wasm_bg.wasm pkg/hello_wasm_bg.wasm |
-Oz はコードサイズ最適化モードです。実際の差はプロジェクト規模にもよりますが、30 % 前後の削減 が期待できます。
5‑4. CDN 配信を想定したファイル構成
| ファイル | 配布先例 |
|---|---|
hello_wasm_bg.wasm |
/static/hello_wasm_bg.wasm |
hello_wasm.js / *_bg.js |
同上(同一ディレクトリ) |
*.wasm.map |
デバッグ用にオプションで配布 |
本番環境では キャッシュヘッダー と Content‑Encoding: gzip/br を有効にすると、さらに転送サイズが削減できます。
6. トラブルシューティングまとめ
| 症状 | 主な原因 | 対策 |
|---|---|---|
Failed to load wasm(ステータス 404) |
ローカルサーバが .wasm の MIME を正しく設定していない |
Node の serve、Python の http.server、または Trunk が自動で正しいヘッダーを付与 |
Uncaught (in promise) TypeError: instantiateStreaming failed |
CORS ポリシー違反やサーバが application/wasm を返さない |
サーバ側で Content-Type: application/wasm を明示、または npm i -g http-server && http-server -c-1 でテスト |
| Rust の panic がコンソールに表示されない | console_error_panic_hook 未設定 |
上記 5‑2 を参照しビルドフラグを付与 |
| ビルドが遅い/メモリ不足 | デバッグビルドで最適化が無効 | --release(または Cargo の [profile.release])を使用 |
7. 参考情報(公式ドキュメント)
- wasm‑bindgen: https://rustwasm.github.io/docs/wasm-bindgen/
- wasm‑pack: https://github.com/rustwasm/wasm-pack
- Trunk: https://trunkrs.dev/
- binaryen (wasm‑opt): https://github.com/WebAssembly/binaryen
上記は常に最新版が配布されている公式リポジトリです。バージョンアップ情報は GitHub の Release ページや cargo install --list で随時確認してください。
8. まとめ
- rustup + wasm32‑unknown‑unknown を導入すれば、Rust 本体の管理が一元化できる。
- wasm‑pack と Trunk はそれぞれ「npm パッケージ化」「開発サーバ」向けに最適化されており、組み合わせるだけでほぼ完結したフローになる。
- Windows でも scoop / chocolatey を使えば binaryen が手軽に入手でき、ビルドサイズの圧縮が可能。
- デバッグ時は
--debugとconsole_error_panic_hook、リリース時はwasm-opt -Ozを忘れずに適用すれば、開発効率と本番パフォーマンスを両立できる。
この手順通りに環境構築・ビルド・テスト・最適化まで行えば、Rust の安全性と WebAssembly の高速性を活かしたモダンなフロントエンド開発がすぐに始められます。ぜひ実践してみてください。