😎

Rust and Webassemblyのチュートリアルでハマった

2025/01/10に公開

Webassemblyに入門。
そのチュートリアルではまったので。
(チュートリアルは、別記事に書く予定)

Rust: 1.83.0
Node: 23.6.0

な環境です。

結論として、追記した別の解決策 がスマートな解決策です。

事象

https://rustwasm.github.io/docs/book/game-of-life/hello-world.html

上記内容の最後 npm run start を実行したら以下エラーが。。。

$ npm run start
> create-wasm-app@0.1.0 start
> webpack-dev-server

(node:83576) [DEP0111] DeprecationWarning: Access to process.binding('http_parser') is deprecated.
(Use `node --trace-deprecation ...` to show where the warning was created)
? 「wds」: Project is running at http://localhost:8080/
? 「wds」: webpack output is served from /
? 「wds」: Content not from webpack is served from /tmp/wasm-game-of-life/www
? 「wdm」: Hash: 4f20672a5fb469845c2e
Version: webpack 4.43.0
Time: 277ms
Built at: 2025/01/10 19:26:45
         Asset       Size  Chunks             Chunk Names
0.bootstrap.js   6.77 KiB       0  [emitted]
  bootstrap.js    368 KiB    main  [emitted]  main
    index.html  297 bytes          [emitted]
Entrypoint main = bootstrap.js
[0] multi (webpack)-dev-server/client?http://localhost:8080 ./bootstrap.js 40 bytes {main} [built]
[../pkg/wasm_game_of_life.js] 203 bytes {0} [built]
[./bootstrap.js] 279 bytes {main} [built]
[./index.js] 58 bytes {0} [built]
[./node_modules/ansi-html/index.js] 4.16 KiB {main} [built]
[./node_modules/ansi-regex/index.js] 135 bytes {main} [built]
[./node_modules/strip-ansi/index.js] 161 bytes {main} [built]
[./node_modules/webpack-dev-server/client/index.js?http://localhost:8080] (webpack)-dev-server/client?http://localhost:8080 4.29 KiB {main} [built]
[./node_modules/webpack-dev-server/client/overlay.js] (webpack)-dev-server/client/overlay.js 3.51 KiB {main} [built]
[./node_modules/webpack-dev-server/client/socket.js] (webpack)-dev-server/client/socket.js 1.53 KiB {main} [built]
[./node_modules/webpack-dev-server/client/utils/createSocketUrl.js] (webpack)-dev-server/client/utils/createSocketUrl.js 2.91 KiB {main} [built]
[./node_modules/webpack-dev-server/client/utils/log.js] (webpack)-dev-server/client/utils/log.js 964 bytes {main} [built]
[./node_modules/webpack-dev-server/client/utils/reloadApp.js] (webpack)-dev-server/client/utils/reloadApp.js 1.59 KiB {main} [built]
[./node_modules/webpack-dev-server/client/utils/sendMessage.js] (webpack)-dev-server/client/utils/sendMessage.js 402 bytes {main} [built]
[./node_modules/webpack/hot sync ^\.\/log$] (webpack)/hot sync nonrecursive ^\.\/log$ 170 bytes {main} [built]
    + 23 hidden modules

ERROR in ../pkg/wasm_game_of_life_bg.wasm
Module parse failed: Unknown element type in table: 0xNaN
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
Error: Unknown element type in table: 0xNaN
    at new CompileError (/tmp/wasm-game-of-life/www/node_modules/@webassemblyjs/helper-api-error/lib/index.js:40:109)
    at parseTableType (/tmp/wasm-game-of-life/www/node_modules/@webassemblyjs/wasm-parser/lib/decoder.js:984:13)
    at parseTableSection (/tmp/wasm-game-of-life/www/node_modules/@webassemblyjs/wasm-parser/lib/decoder.js:1240:24)
    at parseSection (/tmp/wasm-game-of-life/www/node_modules/@webassemblyjs/wasm-parser/lib/decoder.js:1375:25)
    at Object.decode (/tmp/wasm-game-of-life/www/node_modules/@webassemblyjs/wasm-parser/lib/decoder.js:1696:25)
    at decode (/tmp/wasm-game-of-life/www/node_modules/@webassemblyjs/wasm-parser/lib/index.js:248:21)
    at WebAssemblyParser.parse (/tmp/wasm-game-of-life/www/node_modules/webpack/lib/wasm/WebAssemblyParser.js:74:19)
    at /tmp/wasm-game-of-life/www/node_modules/webpack/lib/NormalModule.js:482:32
    at /tmp/wasm-game-of-life/www/node_modules/webpack/lib/NormalModule.js:358:12
    at /tmp/wasm-game-of-life/www/node_modules/loader-runner/lib/LoaderRunner.js:373:3
    at iterateNormalLoaders (/tmp/wasm-game-of-life/www/node_modules/loader-runner/lib/LoaderRunner.js:214:10)
    at Array.<anonymous> (/tmp/wasm-game-of-life/www/node_modules/loader-runner/lib/LoaderRunner.js:205:4)
    at Storage.finished (/tmp/wasm-game-of-life/www/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js:43:16)
    at /tmp/wasm-game-of-life/www/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js:79:9
    at /tmp/wasm-game-of-life/www/node_modules/graceful-fs/graceful-fs.js:78:16
    at FSReqCallback.readFileAfterClose [as oncomplete] (node:internal/fs/read/context:68:3)
 @ ../pkg/wasm_game_of_life.js 1:0-52 4:15-19 5:0-21
 @ ./index.js
 @ ./bootstrap.js

ERROR in chunk 0
236d282200ca012144ee.module.wasm
/tmp/wasm-game-of-life/pkg/wasm_game_of_life_bg.wasm
unexpected end
? 「wdm」: Failed to compile.

解決策

https://github.com/rustwasm/wasm-bindgen/issues/4211#issuecomment-2447799119

上記に記載している通り、Cargo.tomlに以下を追記して、wasm-pack build することで解決。

[build]
strip = true

[profile.dev]
strip = true

[profile.release]
lto = true
opt-level = 'z'
strip = true

[build], [profile.dev]は追記。[profile.release]はすでに記載あるので書き換え。

なぜこれで解決するかはわかってないです。。。
分かるようにお勉強

別の解決策

ふと思って、AI君に解決策を聞いてみた。
そしたら

"devDependencies": {
  "webpack": "^5.0.0",
  "webpack-cli": "^4.0.0",
  "webpack-dev-server": "^4.0.0"
}

webpack がバージョン 5 以上でない場合、wasm モジュールの取り扱いに問題が発生する可能性があります。

と。調べてみると2025/01/10現在の最新バージョンは、5.97.1
使っていたのは、以下の通り

  "devDependencies": {
    "hello-wasm-pack": "^0.1.0",
    "webpack": "^4.29.3",
    "webpack-cli": "^3.1.0",
    "webpack-dev-server": "^3.1.5",
    "copy-webpack-plugin": "^5.0.0"
  }

確かに古い。。。。

ということで、AIに従って変更してみた。package.jsonを変えてみて実行。
以下が結果

> create-wasm-app@0.1.0 start
> webpack-dev-server

<i> [webpack-dev-server] Project is running at:
<i> [webpack-dev-server] Loopback: http://localhost:8080/
<i> [webpack-dev-server] On Your Network (IPv4): http://172.25.126.255:8080/
<i> [webpack-dev-server] Content not from webpack is served from '/tmp/wasm-game-of-life/www/public' directory
(node:84582) [DEP_WEBPACK_COMPILATION_ASSETS] DeprecationWarning: Compilation.assets will be frozen in future, all modifications are deprecated.
BREAKING CHANGE: No more changes should happen to Compilation.assets after sealing the Compilation.
        Do changes to assets earlier, e. g. in Compilation.hooks.processAssets.
        Make sure to select an appropriate stage from Compilation.PROCESS_ASSETS_STAGE_*.
(Use `node --trace-deprecation ...` to show where the warning was created)
asset bootstrap.js 268 KiB [emitted] (name: main)
asset index_js.bootstrap.js 6.03 KiB [emitted]
asset index.html 297 bytes [emitted]
runtime modules 31.6 KiB 15 modules
modules by path ./node_modules/ 175 KiB
  modules by path ./node_modules/webpack-dev-server/client/ 71.8 KiB 16 modules
  modules by path ./node_modules/webpack/hot/*.js 5.17 KiB 4 modules
  modules by path ./node_modules/html-entities/lib/*.js 78.9 KiB 4 modules
  ./node_modules/ansi-html-community/index.js 4.16 KiB [built] [code generated]
  ./node_modules/events/events.js 14.5 KiB [built] [code generated]
modules by path ../pkg/ 2.68 KiB
  ../pkg/wasm_game_of_life.js 203 bytes [built] [code generated]
  ../pkg/wasm_game_of_life_bg.wasm 1.33 KiB [built] [code generated] [1 error]
  ../pkg/wasm_game_of_life_bg.js 1.15 KiB [built] [code generated]
modules by path ./*.js 337 bytes
  ./bootstrap.js 279 bytes [built] [code generated]
  ./index.js 58 bytes [built] [code generated]

ERROR in ../pkg/wasm_game_of_life_bg.wasm 1:0
Module parse failed: Unexpected character '' (1:0)
The module seem to be a WebAssembly module, but module is not flagged as WebAssembly module for webpack.
BREAKING CHANGE: Since webpack 5 WebAssembly is not enabled by default and flagged as experimental feature.
You need to enable one of the WebAssembly experiments via 'experiments.asyncWebAssembly: true' (based on async modules) or 'experiments.syncWebAssembly: true' (like webpack 4, deprecated).
For files that transpile to WebAssembly, make sure to set the module type in the 'module.rules' section of the config (e. g. 'type: "webassembly/async"').
(Source code omitted for this binary file)
 @ ../pkg/wasm_game_of_life.js 1:0-52 4:15-19 5:0-21
 @ ./index.js 1:0-42 3:0-10
 @ ./bootstrap.js 4:0-20

webpack 5.97.1 compiled with 1 error in 279 ms

結果変わった。。。が、やっぱりエラー
メッセージを読むとwebpack 5 からは試験的機能はデフォルト無効なので、有効にしてねとのこと。

とことんAI君に頼ることにして、聞いてみたら以下の通り。

webpack.config.js ファイルを編集し、以下の設定を追加または修正してください。

module.exports = {
  experiments: {
    asyncWebAssembly: true, // WebAssembly の非同期読み込みを有効化
  },
  module: {
    rules: [
      {
        test: /\.wasm$/, // .wasm ファイルを処理
        type: "webassembly/async", // 非同期 WebAssembly を使用
      },
    ],
  },
};

上記追加したら動きました。。。

補足

まったく関係ないけど、webpack-dev-serverのListen addressとPortを変える場合は以下をwebpack.config.jsに追加してあげる

  devServer: {
    host: "<IPアドレス>", // Listen on all network interfaces
    port: 8080  // Use port 8080
  }

0.0.0.0にしても、localhostともう一個までしか認識してくれず、、、

Discussion