TL;DR; Rust、Node.js、wasm-pack、webpack、そしてwebpack-dev-serveが必要です
2019年3月の時点で、何が必要がわからなかったのでまとめました。
Rustを使ってWebAssemblyを出力するまでの流れ
RustはそのままでもWebAssembly(以下、WASM)に出力することはできます。しかしJavaScriptとの連携を考えると、wasm-packを使うのが、一番簡単です。
プロジェクトの作成から、作ったWASMをWebブラウザーで動かすまでの流れは、こんな感じです:
- Cargoでプロジェクトを作成
- Rustでプログラムを書く
- wasm-packを使って、RustをWASMを出力。
- WASMを利用するJSを書く
- JSとWASMをバンドルする
- サーバーで作ったものを配信する
- ブラウザーでアクセスする
Rustをビルドした後に、JSをビルドするというところがコツです。
プロジェクトを始める前に必要なもの
プロジェクトを始める前に、次の2つは必要です。
rustupの使い方はこちらの記事を参照してください。
wasm-packのインストールは、Rustをインストールした後です。次のようにCargoを使えばインストールできます。
% cargo install wasm-pack
プロジェクトの準備
Cargoを使ってプロジェクトを作成します。ライブラリとして作ります。
% cargo new --lib hello-world
つくったら、cargo.toml
に依存するライブラリを追加していきます。最低でも、次のようにwasm-bindgenは追加します。
[package]
name = "greet"
version = "0.1.0"
authors = ["chikoski <some.email.address@example.com>"]
edition = "2018"
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2.37"
詳しくはwasm-bindgenのドキュメントを参照してください。
JavaScript開発の準備
wasm-packコマンドでビルドすると.wasmファイルに加えて、WASMからエクスポートされた関数をラップした関数や、文字列やオブジェクトをWASM-JS間でやり取りするためのユーティリティなどが定義されているJSファイルも作成されます。これらはpkg
フォルダ以下に配置されています。
/
├── Cargo.lock
├── Cargo.toml
├── bin
├── pkg
├── src
├── target
├── wasm-pack.log
ビルド直後のプロジェクトフォルダ直下は上記のようになっています。
JSプロジェクトへの組み込みかた
作成したWASMファイルをJSへ組み込むには、2つの選択肢があります。
- JSのプロジェクトを別に作り、そちらからnpmパッケージとしてインポートする
- Rustのソースコード中に、JSのコードも配置する
どちらの場合でもWebpackを使ってビルドします。フォルダの配置が異なるので、webpack.config.js
の内容や、package.json
の記述が少し変わります。
Webpackを使ってビルド
wasm-packで出力されるJSは、次のようにWASMファイルをインポートしています。WASMのモジュールと、JSのモジュールの相互運用は提案されていますが、利用できる実行環境はありません。したがって、Webpackを使いビルドして、現在の環境でも利用できるコードを生成します。
プラグインなしでもWebpackはWASMを処理できます。もし、JSのビルドに合わせてRustのビルドも行いたい場合は、@wasm-tool/wasm-pack-pluginというプラグインを使います。
Webサーバーに配置する際の注意
Webpackで出力されたコードは、WASMファイルをストリームコンパイルします。
WASMファイルはapplication/wasm
というコンテントタイプで配信されなければなりません。webpack-dev-serverは特に設定する必要ありませんが、他の場合は設定の追加が必要な場合があります。
まとめ
wasm-packとWebpackが、よしなにしてくれます。特にWebpackは特別なプラグインなしで使えるのは楽でした。
どういうコードを書けば良いかは、wasm-bindgenのチュートリアルをやると、見えてくると思います。