はじめに
wasmに挑戦してみようとHello, worldをやってみようとしました。
公式っぽいドキュメントとしてはググると次のものが見つかりました:
最初は1つめのドキュメントを見ながらやり始めたのですが、どうも記述が古いっぽい気がしてリポジトリを見てみると最終コミットが5ヶ月前で、ちょっとどうかと思ったので2つめを見てみたのですが、こちらはこちらで本当にHello, world部分しか説明されておらず先に進めそうもありませんでした。
それ以外のものを探したところ、 https://rustwasm.github.io/ から辿れる次のドキュメントを見つけました:
…がこちらも少し現状に即していないように見えました。
以下、上記のドキュメントを継ぎ接ぎしてHello, worldを作成してみた記録です。
プロジェクト作成の前に
ツールの種類と概要
似た名前のツール/コマンドが登場するので最初に一覧を見ておくと良いかと考えます。The Rust Wasm Bookに説明があります。
プロジェクトテンプレート
前述リンク 5.3. Project Templates 先には3種類のプロジェクトテンプレートが紹介されています。
いろいろなチュートリアルを見ていると、このテンプレートが事前説明無く使われている(あるいはテンプレート無しで進めていく)のでどのチュートリアルを参考にすれば良いのか混乱しました。
ですのでここで簡単に触れておきます。
- wasm-pack-template
-
RustのコードをWasmプロジェクトにパッケージングするためのテンプレート。JavaScriptの世界とは無関係です(ので
package.json
などが含まれない)。 - create-wasm-app
-
Rustから生成したWasmのNPMパッケージを利用するようなJavaScriptプロジェクトのテンプレート。Rustの世界とは無関係です(ので
Cargo.toml
などが含まれない)。 - rust-webpack-template
-
JavaScriptプロジェクトですが、一部をRustで実装し、Wasmに変換して利用するようなプロジェクト。
"Hello, worldをWasmでやってみよう!"という場合、おそらく利用することになるのは rust-webpack-template ではないでしょうか。
プロジェクト作成
The wasm-pack Book の 5.1. Hybrid applications with Webpack が rust-webpack-template
を利用したプロジェクト作成チュートリアルになっているのでこれをなぞります。
npm init rust-webpack wasm-app
( wasm-pack
のチュートリアルで用いられているのは wasm-pack-template
でなく rust-webpack-template
…これだけで混乱するには十分です…)
ちなみに yarn create rust-webpack
は何故か失敗します(こちら と同じ原因でしょうか)。
ですので、 yarn
を利用する場合もここだけ npm
コマンドで実行する必要がありそうです。
Hello, world 加筆
上で参考にしたチュートリアルの続きを進めたいのですが、 Your Rust Crate に書かれているコード
// Your code goes here! let p: web_sys::Node = document.create_element("p")?.into(); p.set_text_content(Some("Hello from Rust, WebAssembly, and Webpack!"));
を追加してもコンパイルが通りません。
これを解決するには The wasm-bindgen
Guide の 1.9. web-sys: DOM hello world に書かれている通り、 web-sys
の features 設定を行う必要があります。
また、そもそもコード自体も間違っており features 追加した後コード修正も必要になります。これも上記ページが参考になります。
[dependencies.web-sys] version = "0.3.22" features = ["console", 'Document', 'Element', 'HtmlElement', 'Node', 'Window']
// Your code goes here! let window = web_sys::window().expect("no global `window` exists"); let document = window.document().expect("should have a document on window"); let body = document.body().expect("document should have a body"); let val = document.create_element("p")?; val.set_text_content(Some("Hello from Rust, WebAssembly, and Webpack!")); body.append_child(&val)?;