LoginSignup
3
3

More than 1 year has passed since last update.

svelte-kitでwasm-packを使う

Last updated at Posted at 2021-11-08

wasm-packを使って作成したwasmのパッケージを利用していた時にsvelte-kitのビルドにはまったのでメモします.

svelte-kitでwasmのパッケージを読み込む

svelte-kitは内部でviteを利用しているのですが,viteでwasm-packで作成したパッケージを利用するためには

wasm-pack build --target web

のようにターゲットを指定します.--targetはwasm-packのオプション なので,featuresの指定をするときはwasm-pack build --target web -- --features console_error_panic_hookのように前に--を入れます.他のビルドターゲットにしたい場合もあると思いますが,viteで読み込む方法は分かりませんでした.
javascript側では普通に以下のようにimportできます.以下はwasm-bindgenでinterface(IAppOption)とクラス(CanvasApp)を定義した例です.

import init, {CanvasApp} from '$lib/wasm/pkg/wasm';
import type {IAppOption} from '$lib/wasm/pkg/wasm';

上ではビルドで生成したjsファイルを読み込んでいますが,$lib/wasm/pkgのようにpkgディレクトリを指定することもできます.デフォルトで読み込まれるinitは非同期関数であり,initが完了した後にCanvasAppが利用可能になります.具体的には

import init, {CanvasApp} from '$lib/wasm/pkg/wasm';
import type {IAppOption} from '$lib/wasm/pkg/wasm';
import {onMount} from "svelte";

onMount(async () => {
    await init();
    const app_opt: IAppOption = {...何かオプション};
    const canvas_app = new CanvasApp(app_opt);
    ...何か処理
});

のように利用します.こちらはsvelte-kit dev(npm run dev)では問題なく動きますが,svelte-kit build(npm run build)では

Error: 'new URL(url, import.meta.url)' is not supported in SSR.

というエラーがでます.これはインポートしたjsファイル内のURLコンストラクタがnodeで動かないためです.

svelte-kit build が通るようにする

こちらにissueが上がっているので,紹介されているテンプレートを参考にします.以下はrustプロジェクトのディレクトリがルートから./src/lib/wasmである場合の例です.

.rsw.json
{
 "crates_path": "./src/lib/",
 "crates": [
 "wasm"
 ]
}

fix-new-urls.js
// Temporary fix for https://github.com/vitejs/vite/issues/5169
import { readFileSync, writeFileSync } from 'fs';

const re = /[^\n]*new URL[^\n]*/g;
for(let crateName of JSON.parse(readFileSync("./.rsw.json", "utf8")).crates) {
 try {
 const crates_path = JSON.parse(readFileSync("./.rsw.json", "utf8")).crates_path
 const fileName = crates_path + crateName + "/pkg/" + crateName + ".js";
 writeFileSync(fileName, readFileSync(fileName, "utf8").replace(re, ""));
 } catch {}
}

をプロジェクトのルートに用意しnode fix-new-urlssvelte-kit buildの前に実行します(jsファイルを変更してしまうのでtsconfigがvscode上でエラーを出します).ビルド時のエラーの該当部分を削除しています.
するとsvelte-kit buildが通るようになります.以上でビルドは成功しますが
ブラウザで

WebAssembly.instantiate(): Argument 0 must be a buffer source or a WebAssembly.Module object

というエラーが出てwasmを読み込めなくなってしまいます.そこで javascript側を以下のように変更します.

import init, {CanvasApp} from '$lib/wasm/pkg/wasm';
import type {IAppOption} from '$lib/wasm/pkg/wasm';
import wasm_path from "$lib/wasm/pkg/wasm_bg.wasm?url";
import {onMount} from "svelte";

onMount(async () => {
    await init(wasm_path);
    const app_opt: IAppOption = {...何かオプション};
    const canvas_app = new CanvasApp(app_opt);
    ...何か処理
});

init関数にwasmファイルのパスを与えるだけです.これでnpm run devでもnpm run buildでも動くようになります.

3
3
0

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
  3. You can use dark theme
What you can do with signing up
3
3