何番煎じかわかりませんが、表題のとおりです。
ディレクトリ構成
今回のディレクトリ構成は以下になります。
RustのコードとJavaScript(Web)のコードでディレクトリ分けました。
Rust側のプロジェクトがwasmディレクトリ、
JavaScript側のプロジェクトがwwwディレクトリです。
wasm_from_rust
+-- wasm
+-- Cargo.toml
+-- pkg
+-- src
+-- lib.rs
+-- www
+-- pkg
+-- dist
+-- node_modules
+-- package.json
+-- src
+-- index.html
+-- index.js
+-- webpack.config.js
手順
1. ルートディレクトリを作成する
$ mkdir wasm_from_rust
$ cd wasm_from_rust
2. Rust側
2.1 Rustプロジェクトを作成する
$ cargo new --lib wasm
$ cd wasm
2.2 WebAssemblyを使用するための参照を追加する
WebAssemblyを使用するため、Cargo.tomlに記述していきます。
libにcdylib、dependenciesにwasm-bindgenです。
[package]
name = "wasm"
version = "0.1.0"
authors = ["nabezokodaikon <nabezoko.daikon@gmail.com>"]
edition = "2018"
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2.40"
参照解決のため、ビルドしておきましょう。
$ cd wasm
$ cargo build
2.3 Rustでコードを書く
では、Rustでコードを書いていきましょう。
引数で受け取った文字列を少し加工して、アラートを表示するだけのものです。
extern crate wasm_bindgen;
use wasm_bindgen::prelude::wasm_bindgen;
#[wasm_bindgen]
extern "C" {
pub fn alert(s: &str);
}
#[wasm_bindgen]
pub fn greet(name: &str) {
alert(&format!("Hello, {}!", name));
}
2.4 Rustのnpmパッケージを作成する
npmのパッケージを生成するwasm-packをインストールします。
$ cargo install wasm-pack
作成したRustのコードで、npmのパッケージを作成するコマンドを実行します。
$ wasm-pack build
コマンドが成功すると、pkgディレクトリが作成されます。
wasm_from_rust
+-- wasm
+-- Cargo.toml
+-- pkg <--- 作成したnpmパッケージディレクトリ
+-- src
+-- lib.rs
3. JavaScript側
ここで一度プロジェクトのルートディレクトリに戻っておきましょう。
cd ../
3.1 npmコマンドで初期化する
$ mkdir www
$ cd www
$ npm init
3.2 必要なnpmパッケージをインストールする
先程作成したRustのnpmパッケージ。
$ npm install ../wasm/pkg
Rustで生成したパッケージを読み込むためのパッケージ。
$ npm install --save-dev @wasm-tool/wasm-pack-plugin
webpack関連のパッケージ。
$ npm install --save-dev webpack
$ npm install --save-dev webpack-cli
$ npm install --save-dev html-webpack-plugin
開発用サーバのパッケージ。
$ npm install --save-dev webpack-dev-server
3.3 webpackの設定ファイルを作成する
以下になります。
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const WasmPackPlugin = require("@wasm-tool/wasm-pack-plugin");
module.exports = {
mode: "development",
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "index.js"
},
plugins: [
new HtmlWebpackPlugin(),
new WasmPackPlugin({
crateDirectory: path.resolve(__dirname, "../wasm")
})
]
};
3.4 JavaScriptのコードを書く
準備が整ったので、JavaScript側のコードを書きます。
$ mkdir src
$ touch src/index.html
$ touch src/index.js
3.4.1 index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>wasm from Rust</title>
</head>
<body>
<script src="./index.js"></script>
</body>
</html>
3.4.2 index.js
一つポイントなんですが、wasmをインポートする場合、Dynamic importでなければなりません。
const js = import("../node_modules/wasm/wasm.js");
js.then(js => {
js.greet("WebAssembly");
});
以上です
後はwebpackでビルドして、開発用サーバを起動すれば実行できます。
$ ./node_modules/.bin/webpack --config webpack.config.js
$ ./node_modules/.bin/webpack-dev-server