wasm-pack でWebAssembly吐いて動かしてみたらエラーが出るんですケド💦

こんにちは、Webエンジニアです。
2017年ぐらいに「ビットコインはイイゾースゴイゾー😁ただ価格上がりすぎちゃったので😥アルトコイン買お😘」って風潮に脳死で突っ込んで、フジコイン とか ストロングハンド とかなんとかって草コインいっぱい買っちゃってさ、「仮想通貨わかんね」つって遠のいてたんだけどさ、最近仮想通貨盛り上がってきたじゃない?二の轍を踏みにきたよ。

ガチ界隈のみんなはさ、仮想通貨の価額には興味がなくて、 Decentralized なテクノロジーやコミュニテイなんかに興味があるんだろうし、僕みたいな貧困情弱投機家は嫌いなんだろうけど。まあでもみんながいい記事を書いてくれることでさ、僕が分散型ネットワークに詳しくなってさ、儲かるコインがわかるようになるかもしれないからさ、頑張ってよ。

で、Rustもさ、みんなが「イイゾー」って言うから始めてみたのよ。みんながいいっていうから多分いいんだよね。で、Yew っていうRust -> Wasm のフロントエンドフレームワーク触ってみたわけ。で、タイトル。

こちらを参考にセットアップしてみて、なんとかビルドまでは行けたんだけど、
ブラウザで確認してみると

Failed to load module script: The server responded with a non-JavaScript MIME type of "application/wasm". Strict MIME type checking is enforced for module scripts per HTML spec.

だってさ。

ESModule として dynamic import してるけど、ESM として扱うなら MIME が application/javascript じゃないとダメじゃない? とのこと。

これはwasm-packのデフォルトオプションが悪くて、詳しくは↓とか読むといいんだけど、
https://rustwasm.github.io/wasm-pack/book/commands/build.html

dynamic import で wasm のモジュールをインポートするのはどのブラウザも未対応みたい。
Webpackでうまいことやってね、て意図でデフォルト挙動がこうなってるみたいなんだけど、僕はちょっとした理由があってWasmWebpackPluginにうまいことやってもらいたい。
そこで、 wasm-pack に --target=web ってオプションを渡す。

webpack.config.js の WasmWebpackPlugin のコンストラクタの引数をいじるとこれが調整できる。

new WasmPackPlugin({
                crateDirectory: ".",
                extraArgs: "--no-typescript",
                outDir: "dist",
                outName: "index",
                forceWatch: true,
            }),

これが

new WasmPackPlugin({
                crateDirectory: ".",
                extraArgs: "--no-typescript --target web",
                outDir: "dist",
                outName: "index",
                forceWatch: true,
            }),

こう。

これによって、吐き出される dist/index.js が

import * as wasm from "./index_bg.wasm";
export * from "./index_bg.js";
wasm.__wbindgen_start();

から

let wasm;
const heap = new Array(32).fill(undefined);
heap.push(undefined, null, true, false);
function getObject(idx) { return heap[idx]; }
function _assertBoolean(n) {
    if (typeof(n) !== 'boolean') {
        throw new Error('expected a boolean argument');
    }
}
let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
~~~~
あと500行ぐらい

になりました。

あとは、エントリーポイントのJSをいい感じにして、

(async () => {
  const { default: init } = await import(
    /* webpackIgnore: true */ "/wasm/index.js"
  );
  const wasm = await init();
  wasm.run_app();
})();

これで一旦動いた。

ただ、以上の方法は正攻法ではないので --target web しないでも動く、特殊な要件がなければテンプレート通りの方法をおすすめします。

この続き : 0字 / 画像 0枚
100

会員登録 / ログインして続きを読む

参加しているキャンペーン

関連記事

記事を書いた人

全財産JPY

SNSにシェア

このクリエイターの人気記事

OBSとAWSでライブ配信をする①

281

AWSでビットコフルノードを建てる場合のランニングコスト試算

132

OBSとAWSでライブ配信をする③

121