【Golang】TinyGo で WebAssembly.instantiate(): Import #0 module="wasi_snapshot_preview1" error: module is not an object or function


Docker の TinyGo で疲労コンパイる

TinyGo の Docker イメージ tinygo/tinygo:latestwasm(WebAssembly のバイナリ)をビルドして実行したら、"wasi_snapshot_preview1" エラーがブラウザのデベロッパーツールのコンソールに表示される。

consoleログ
WebAssembly.instantiate(): Import #0 module="wasi_snapshot_preview1" error: module is not an object or function

wasi_snapshot_preview1 モジュールがないのはわかるのですが、よくわりません。でも Go で wasm をコンパイルすると動くんです。

WebAssembly.instantiate(): Import #0 module= "wasi_snapshot_preview1" error: module is not an object or function」でググっても node.js の内容ばかり。Golang のスポンサー情報が欲しいのです

TinyGo 公式の "wasi_snapshot_preview1" がらみの Issues を見ても、むしろ wasi_unstable だったのを wasi_snapshot_preview1 にしたくらいの情報しかありません。どうしよう。

TL; DR (今北産業)

  1. 原因
    • *.wasm バイナリと Javascript の関数を紐づける wasm_exec.js で違うものが使われています。
  2. wasm_exec.js は、使用しているコンパイラが提供している wasm_exec.js を使うこと。
    • Go のマスターブランチから持って来てはいけない。
  3. wasm_exec.jsの保存先:
    • コンパイラが Go の場合:
      • $(go env GOROOT)/misc/wasm/wasm_exec.js
    • コンパイラが TinyGo の場合:
      • /usr/local/tinygo/targets/wasm_exec.js

TS; DR 正妻公式ドキュメント嫁に叱られる)


所感

「Go で wasm 動いた!」と Hello, world! したくらいで喜んでいたのも束の間。せっかちなものだから次の基本を踏まずに「いままで作ったアプリを wasm る!」と思うも test が思うように動かない。わざと失敗させてるエラーもパスしてしまうのです。

「Golang で wasm るベストプラクティス」なる記事を読んでいたら「wasmgzip するのがブラウザ(ネットワーク)に優しいけど、TinyGo 使ったらもっと小さくなるでよ」的なことが書いてありました。

確かに、なんかそれっぽいことはネットサーフィンしていて見かけた気がします。しかし、公式ドキュメントをしっかり読まないで思いつきで動いちゃうものだから、動くものも動かない。ちゃんと書いてありました。

どうせまた忘れるので、未来の自分のググラビリティとして備忘録Qiitaに残します。