search
LoginSignup
165

More than 1 year has passed since last update.

posted at

updated at

Next.jsとRustのTypeScriptなWebAssembly生活

なんかwasmを直読み出来るんだけど

Webpackがwasmの読み込みをサポートしているので、Next.jsでもちょっと設定を追加するだけで動作が確認出来ました
TypeScriptの定義まで自動で行われるので、連携する上で迷うところがありません

今回作成したコード
https://github.com/SoraKumo001/next-wasm

RustでWebAssemblyの生成

Rustのインストール

https://www.rust-lang.org/tools/install
これが無いと話にならないので、とりあえずインストールする必要があります

wasm-packのインストール

以下を実行してwasm-pack入れるとRustでWebAssemblyが簡単に生成できるようになります
cargo install wasm-pack

必要なコード

Cargo.toml
[package]
name = "wasm"
version = "0.1.0"
edition = "2018"
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2.74"
src/lib.rs
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn sums(value: i32) -> i32 {
    let mut a: i32 = 0;
    for i in 1..value+1 {
        a += i;
    }
    a
}

1から任意の値までの合計を計算するプログラムです
RustからWebAssemblyを使う場合、あんまりゴチャゴチャ設定を書く必要はありません

コンパイル

wasm-pack build

以上のコマンドでWebAssemblyが出力されます

出力ファイル

以下の6つのファイルが生成されます

.gitignore
wasm.d.ts
wasm.js
wasm_bg.js
wasm_bg.wasm
wasm_bg.wasm.d.ts

必要なファイル

Next.jsから利用するときに必要なのは、以下の2つのファイルだけです
TypeScriptの定義も含まれています

wasm_bg.wasm
wasm_bg.wasm.d.ts

Next.js側

環境を整える

必要最低限のパッケージをインストールします

yarn init -y
yarn add next react react-dom
yarn add -D typescript @types/node @types/react

WebPackの設定

本来はasyncWebAssemblyをtrueにするだけで良いはずなのですが、webassemblyModuleFilenameの設定をいじらないとnext devでは動くもののnext buildでエラーになります

next.config.js
module.exports = {
  webpack: (config, { isServer }) => {
    config.experiments = {
      asyncWebAssembly: true,
    };
    config.output.webassemblyModuleFilename = (isServer ? '../' : '') + 'static/wasm/webassembly.wasm';
    return config;
  },
};

Next.jsからwasmを呼び出すコード

なんとwasmを直接import出来ます
TypeScriptの定義も自動生成されているので、何事も無かったかのように普通に呼び出して使えます

src/pages/index.tsx
import { sums } from "../lib/wasm_bg.wasm";
import { useState } from "react";

const App = () => {
  const [value, setValue] = useState(0);
  return (
    <div>
      <input
        onChange={(e) => {
          const v = Number(e.target.value);
          !isNaN(v) && setValue(sums(v));
        }}
      />
      <div>{value}</div>
    </div>
  );
};

export default App;

動作確認

WebAssembly化したRustの関数から値が返ってきています

シーケンス 03.gif

まとめ

ヤバいほど超簡単にWebAssemblyが使えます
wasmの中身がよく分かっていなくてもTypeScriptの定義があるので、何の違和感も無く使えます
Rustのソースを監視してファイル更新時にwasm-packを実行すると、さらに開発効率が上がりそうです

今後、WebAssemblyでスレッドサポートが標準化したら、そのパワーを生かした様々なライブラリが作られることが予想されます
そんな時代が来たらWeb開発の手法が大きく変わっていくかもしれません

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
165