Rust 🦀 and WebAssemblyのチュートリアルを読む
Rust 🦀 と Wasm の "Hello, World!"
本記事は、筆者がRustとWasmを学ぶために以下のドキュメントを読み進めた過程を記すものです。 最終的にライフゲームの完成を目指しますが、とりあえず今回はHello,World!までです。
RustとWasm
Rust
2022年現在とても人気のある言語。あらゆるLinuxコマンドのオルタナティヴの多くがRustで書かれている印象を受けます。いろいろ良い点があるが本筋ではないので省略、というより詳しくは知りません。
Wasm
WebAssembly。ウェブブラウザを含むあらゆる環境内で実行できるプログラミング言語。とても注目されています。よく見るサンプルがRustで書かれたプログラムをWasmにコンパイルしてブラウザで実行する。この記事でもそれをします。
セットアップ
用意するもの
Rustの基本的なツールチェイン
rustup
,rustc
,cargo
wasm-pack
cargo install wasm-pack
cargo-generate
cargo install wasm-pack
参考記事
npm
パッケージマネージャ等を使ってインストール。もし既にインストールされている場合は最新版にアップデートする。
npm install npm@latest -g
私はバージョンマネージャーにvolta
を使っているので、それでバージョンを切り替えました。
volta install node@latest
Hello, World!
Rust&Wasmのプロジェクトテンプレートが用意されているので活用します。プロジェクト名が聞かれるので好きな名前を入力する。今回はチュートリアルに従ってwasm-game-of-life
cargo generate --git https://github.com/rustwasm/wasm-pack-template
cd wasm-game-of-life
構成ファイル
Cargo.toml
依存関係やメタデータを指定するファイル。
lib.rs
WebAssemblyにコンパイルするRustクレートのルートファイル。
utils.rs
wasmにコンパイルされたRustを使いやすくするためのユーティリティを提供するファイル。
プロジェクトをビルドする
wasm-pack build
ビルドで出力されたファイル。
wasm_game_of_life_bg.wasm
.wasm
は、RustソースからコンパイルされてたWebAssemblyのバイナリファイル。
wasm_game_of_life.js
.js
は、wasm-bindgenによって生成され、DOMとJS関数をRustにインポートし、Wasm関数のAPIをJSに公開するためのJSグルーが含まれているファイル。
wasm_game_of_life.d.ts
.d.ts
は、JSのグルーのためのTSの方宣言が含まれているファイル。
package.json
生成されてJSとWasmパッケージに関するメタデータが含まれている。npmを使ったプロジェクトで生成されるpackage.jsonと同じ。
Webページに落とし込む
npm init wasm-app www
🦀 Rust + 🕸 Wasm = ❤
www/package.json
webpackとwebpack-dev-serverとの依存関係、npmに公開されているhello-wasm-packの依存関係が事前に設定されている。
www/webpack.config.js
webpackとローカル開発サーバの設定ファイル。特にいじる必要はない。
www/index.html
Webページのルートとなるhtmlファイル。
www/index.html
Webページで使うJSのエントリーポイント。
依存関係のインストール
cd www
npm install
ローカルのwasmパッケージ(wasm-game-of-life)を使うように、package.json
に依存関係を追加する。
"dependencies": { "wasm-game-of-life": "file:../pkg" },
index.js
を編集して、wasm-game-of-life
をインポートするようにさせる。
import * as wasm from "wasm-game-of-life";
wasm.greet();
新しい依存関係をインストール
npm install
ローカルで動かす
npm run start
エラーが発生
ERR_OSSL_EVP_UNSUPPORTED
OpenSSL 3.0関連のエラーの模様。対処策として次のようにすると解消されます。
export NODE_OPTIONS=--openssl-legacy-provider
参考文献
練習問題
greet関数が引数を受け取れるように変更し、自分の名前が表示されるように変更する。
pub fn greet(name: &str) {
alert(&format!("Hello, {}!", name));
}
wasm.greet("k41531");
Discussion