WebAssemblyでHello, World! [Rust]
どうも、二週間に一回ブログ更新という目標を早くも諦めたWhiteShirtです。一か月に一回でいいか……。
WebAssemblyとは?
WebAssembly(以下WASM)JavaScriptの改良版として開発が進められている実行可能なバイナリコードです、専用の仮想マシンで実行します。C、C++、Rustなどでソースコードを書き、それをWASMにコンパイルして使います。
WebAssemblyのメリット
JavaScriptと比べて以下のような利点があります。
– 事前にコンパイルするので動作が高速
– バイナリコードなのでサイズが小さい
– 静的型付け言語で開発できる
0.事前準備
今回はRustを使ってHello Worldします。インストールはここから。
wasm-packが必要なのでインストールします。
Node.jsも必要です。
以下のコマンドを打ってnpmをアップデートしておきます。
npm install npm@latest -g
1.新規プロジェクトを作成
cargo new hello_world --lib
2.Cargo.tomlファイルの書き換え
[package]
name = "hello_world"
version = "0.1.0"
edition = "2018"
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2.75"
wasm-bindgenのおかげでWASMとJavascriptの連携が凄く楽になります。
3. lib.rsの書き換え
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern {
fn alert(s: &str);
}
#[wasm_bindgen]
pub fn greet(name: &str) {
alert(&format!("Hello, {}!", name));
}
3..6: wasm-bindgenを使い、Javascriptのalert関数をexportします。
8..11: exportした関数を使用した関数を定義します。
4.package.jsonを作成
{
"scripts": {
"build": "webpack",
"serve": "webpack-dev-server"
},
"devDependencies": {
"@wasm-tool/wasm-pack-plugin": "1.0.1",
"text-encoding": "^0.7.0",
"html-webpack-plugin": "^3.2.0",
"webpack": "^4.29.4",
"webpack-cli": "^3.1.1",
"webpack-dev-server": "^3.1.0"
}
}
必要なパッケージを書いときます。
5.webpack.config.jsを作成
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
const WasmPackPlugin = require("@wasm-tool/wasm-pack-plugin");
module.exports = {
entry: './index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index.js',
},
plugins: [
new HtmlWebpackPlugin({
template: 'index.html'
}),
new WasmPackPlugin({
crateDirectory: path.resolve(__dirname, ".")
}),
// Have this example work in Edge which doesn't ship `TextEncoder` or
// `TextDecoder` at this time.
new webpack.ProvidePlugin({
TextDecoder: ['text-encoding', 'TextDecoder'],
TextEncoder: ['text-encoding', 'TextEncoder']
})
],
mode: 'development'
};
エントリーポイントなど諸々書いときます。呪文みたいなもんです。
6.htmlファイル, jsファイルを作成
最後にindex.htmlとWASMを呼び出すためのindex.jsを作ります。
htmlは適当に書きます。ひな形のようなもので構いません。大切なのはindex.jsの方です。
const rust = import('./pkg');
rust
.then(m => m.greet('World'))
.catch(console.error);
先ほど書いたRustをコンパイルするとpkgというフォルダが作られ、その中にWASMファイルができるので、そいつをimportし、呼び出します。
7.実行!!
まずpackage.jsonに書いたパッケージをインストールします。
npm install
そしたら実行します。
npm run serve
たったこれだけです。このコマンドを実行するとlib.rsファイルがWASMにコンパイルされ、さらにローカルサーバが立ち上がります。すごい。
そしたら http://localhost:8080/ にアクセスして結果を確認できます。Hello, Worldと表示されます。
先ほど書いたindex.jsファイルを以下のように変えると、ウェブページが自動でリロードされて、結果が変わります。
const rust = import('./pkg');
rust
.then(m => m.greet('WASM'))
.catch(console.error);
感想
WegGLとか使って綺麗なwebコンテンツを作れたらさぞかし楽しいだろうなと思いました。頑張らなくては……。
追記
WASMのプロジェクト作るたびに準備するのは面倒なので、テンプレート作りました。Minimum WebAssembly project for rust
コメント入力