Open4

Rustで作ったwebassemblyをnext.jsで利用する

ピン留めされたアイテム
hysok2hysok2

ウェブアプリを作っています。

アプリの主機能はrustで実装し、webassembly化し、それをnext.jsで読み込んでいます。

このスクラップで、他の方にも役立ちそうな情報をメモします。

私は素人なので、妥当なやり方でないかもしれないです。ツッコミなどありましたらお願い致します。

hysok2hysok2

rustでwebassemblyを含むnpm packageを作る

以下の説明通りにすれば、rustからnpm packageが作れます。wasm-pack便利です。
https://rustwasm.github.io/docs/book/game-of-life/hello-world.html

例えば、wasm-hwというプロジェクト名で、lib.rsを以下とします。

lib.rs
mod utils;

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
struct Test {
    v : i32,
}

#[wasm_bindgen]
impl Test {
    pub fn new(value : i32) -> Test {
        Test {v:value}
    }
    pub fn double(&self) -> i32 {
        self.v * self.v
    }
    pub fn triple(&self) -> i32 {
        self.v * self.v * self.v
    }
}

そしてパッケージをビルドします。

$ wasm-pack build

結果、以下のファイルができます。

pkg/
├── package.json
├── README.md
├── wasm_hw_bg.wasm
├── wasm_hw_bg.wasm.d.ts
├── wasm_hw_bg.js
├── wasm_hw.d.ts
└── wasm_hw.js
hysok2hysok2

wasm-packで作ったパッケージをnext.jsから読む

webPackの設定

next.config.jsを変更

next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  webpack: (config, { isServer }) => {
    config.experiments = {
      asyncWebAssembly: true,
      layers: true,
    };
    config.output.webassemblyModuleFilename =
      (isServer ? "../" : "") + "static/wasm/webassembly.wasm";
    return config;
  },
};

module.exports = nextConfig;

パッケージをコピー

wasm-packで生成したファイルを、next.jsプロジェクトのディレクトリ内にコピーします。

$ cp -r ../wasm-hw/pkg ./

package.jsonに追記

"dependencies" に "wasm-hw": "file:./pkg" を追記。

  "dependencies": {
    ... ,
    "wasm-hw": "file:./pkg"
  }

package.jsonに書かれた依存関係をインストール

$ yarn install

パッケージの呼び出し例

pages/index.tsx
import {Test} from "wasm-hw";

export default function Home() {
  const test = Test.new(4);
  const num = test.triple();
  return (
    <div>
      <p>{num}</p>
    </div>
  )
}

実行

$ yarn next dev

localhost:3000を見ると、64って書かれてます。

以下のリンクを参考にしました。

https://rustwasm.github.io/docs/book/game-of-life/hello-world.html
https://zenn.dev/razokulover/articles/fb64150be7a667
https://qiita.com/SoraKumo/items/d68b78bedda91ff08435

hysok2hysok2

next.jsプロジェクト内のパッケージを更新する

Rustコードを書き換え、wasm-packでパッケージを作り直した後、next.jsで更新(再読込み)する手順は以下となります。

パッケージ生成

$ wasm-pack build

注意:生成するファイルのversionを変更しましょう。
ビルドする前にCargo.tomlをいじりversionを変更するか、生成されたパッケージ内のpackage.json内のversionをいじりましょう。

パッケージをコピー

wasm-packで生成したファイルを、next.jsプロジェクトのディレクトリ内にコピーします。

$ cp -r ../wasm-hw/pkg ./

next.jsプロジェクトに更新したパッケージをインストール

yarn upgrade wasm-hw

パッケージのverを変更しないと、next.jsは更新されたパッケージを読み込まない?

versionを変えなかった場合、更新後のパッケージを上記の通りコピーしたりプロジェクトでupgradeした後、yarn next devを実行すると、古いパッケージを読み込んでしまいます。./node_modules以下のwasm-hwは書き換わっているのですが、何故かそれを読み込んでくれない。