💭

TypeScriptとRollupでWebassemblyを稼働させる: Rustが征く(4)

2021/08/23に公開

@wasm-tool/rollup-plugin-rustの使い方

関連記事:

Rustが征くシリーズ過去記事

------------------- ↓ 前書はここから ↓-------------------

前回はコマンドを駆使して、
ブラウザ上でWebAssemblyを稼働させるようにした。

ただ、やはりJavaScriptはやはり実用性がないので、
TypeScriptで稼働するようにする。
あと前回は最小行程で稼働させるようにしたのだが、
wasm-packコマンドで丸めて使用する。
バンドルはrollup.jsで一括して稼働するようにしよう。

例によってインストール、プロジェクト作成から行うので、
適当に読み飛ばして欲しい。

------------------- ↓ 本題はここから ↓-------------------

Rustのインストール

以下参照のこと
WSL2で作るWindows開発環境: Rustが征く(1)

必要コマンドを追加

Rustインストールと併せて各種コマンドも追加しておく

rustup target add wasm32-unknown-unknown
cargo install cargo-edit wasm-pack

(・∀・) インストール済みです!

Node.jsのインストール

aptでもbrewでもwingetでもお好きなものをどうぞ

node --version
  v16.4.2
npm --version
  7.17.0

wasm-packコマンドでプロジェクト作成

wasm-packコマンドでプロジェクトを作成する。
cargo newでも良かったが、
こちらの方が手間が省ける。
名前は何でも良いが console-log としておこう

wasm-pack new console-log
cd console-log

各種npmパッケージをインストール

TypeScript関連のパッケージをインストール

npm init -y
npm i -D typescript rollup @rollup/plugin-typescript rimraf @wasm-tool/rollup-plugin-rust
npx tsc -t es2021 -m es2020 --allowJs --init

rollup.jsの設定ファイルを作成

rollup.config.mjsを作成する
TypeScriptWebAssemblyの記述を追加

./rollup.config.mjs
import typescript from "@rollup/plugin-typescript"
import rust from '@wasm-tool/rollup-plugin-rust'

export default {
    input: "./src/main.ts",
    output: {
        dir: 'dist/js/',
    },
    plugins:[
        typescript(),
        rust({
            serverPath: "/js/",
        }),
    ]
}

実装作業

TypeScriptの実装作業

フロントエンドプログラム本体。
WebAssemblyを呼び出して、
内包する関数を実行している。

./src/main.ts
(async () => {
  const wasm = await import("../Cargo.toml")
  const {say_hello} = await wasm.default()
  say_hello("dozo")
})()

Rust側実装作業

前回はalertにはろ~わ~るどだったが、
今回はコンソールに出してみよう。

./src/lib.rs
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
extern {
    #[wasm_bindgen(js_namespace=console)]
    fn log(s: String);
}

#[wasm_bindgen]
pub fn say_hello(message: String) {
    log(format!("Hello {} in Rust", message));
}

ビルド開始

cargo buildやwasm packなど個別にコマンドは打たない。
(打っても良いけど)
rollupコマンドだけでビルドを行う

npx rollup -c

index.htmlを用意

最後ににindex.htmlを用意しておく
ファイルを読むだけの簡単なもの

./dist/index.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <script type="module" src="./js/main.js"></script>
</head>
<body>
</body>
</html>

Webサーバー起動

サーバーを起動してアクセスしてみる

npx http-server ./dist

F12でコンソールを出してみると

(・∀・) よんだ?

------------------- ↓ 後書はここから ↓-------------------

rollup-wasmプラグインについて

さてWebAssemblyrollup.jsプラグインだが、
@rollup/plugin-wasm@wasm-tool/rollup-plugin-rust が検索すると出てくる。
正直どちらも微妙だ。
理由はそれぞれ@rollup/plugin-wasmは普通に動かないこと。
@wasm-tool/rollup-plugin-rustは余計なお世話機能があることだ。

@rollup/plugin-wasmはよーわからん

何回試しても使う場面が思いつかない。。。

WebAssemblyrollup.js本家のプラグインに@rollup/plugin-wasmというのがあるが、
使い方がさっぱりわからない
たぶんemscriptenを使う前提なんだと思う。

wasm-packコマンドで必要なコードも生成されるのだが、
rollup/plugin-wasm を噛ませると独自解釈のコードに変わって動かなくなる。

@wasm-tool/rollup-plugin-rustはまだ使える

Cargo.tomlをimportしている記述を読み込んでいる箇所を置換するタイプのプラグイン。
ビルドからデプロイまで一括でやってくれるのでまだ使えるが、
個人的にはあまり使いたくない。

importにCargo.tomlって特殊すぎるし、
ファイル名Cargo-xxxx.jsってのが気に入らないなぁ。

@wesley-clements/rollup-plugin-raw-wasm

個人的にはこれを使いたい
理由は 何もしない から。
変な加工とかCargo.tomlをインポートとかヘンテコなことをせず、
.wasmからpathを取り出して後は普通に使える。

import init, {say_hello} from "../pkg/console-log.js"
import path from "../pkg/console-log_bg.wasm"

(async () => {
    await init(path)
    say_hello("dozo")
})()

設定ファイルは

./rollup.config.js
import { rawWasm } from '@wesley-clements/rollup-plugin-raw-wasm';
 
export default {
  ...
  plugins: [rawWasm({
    publicPath: "./dist/"
  })],
  ...
};

メンテナンス性次第かなぁ。

@wasm-tool/rollup-plugin-rustでビルド時のtypescriptエラー

(Use `node --trace-deprecation ...` to show where the warning was created)
[!] (plugin rpt2) Error: /home/dozo/Repos/Rust/console-log/src/main.ts(1,18): semantic error TS2307: Cannot find module '../Cargo.toml' or its corresponding type declarations.
src/main.ts
Error: /home/dozo/Repos/Rust/console-log/src/main.ts(1,18): semantic error TS2307: Cannot find module '../Cargo.toml' or its corresponding type declarations.

Cargo.tomlが解釈できないというエラー、
その部分を定義しておく必要がある。
以下のファイルを設置する。

./src/global.d.ts
declare module "*.toml"

Discussion