ハクソク

世界を動かす技術を、日本語で。

WebAssemblyに何が起こったのか

概要

  • WebAssembly(Wasm)の現状と実用例を解説
  • Wasmの本質的な役割と設計思想
  • 速度・安全性・移植性の観点からの評価
  • 言語開発や今後の展望について考察
  • WasmがJavaScriptの完全な代替ではない理由を説明

WebAssemblyの現実世界での利用

  • GodotはWasmを使いWeb向けゲームを構築
  • Squoosh.appは画像処理ライブラリの利用にWasmを活用
  • ZellijはプラグインエコシステムにWasmを採用
  • FigmaはC++コードをWasmに変換しブラウザで利用可能化
  • StackblitzRuffleもWasmを重要な基盤技術として使用
  • これらの多くでWasmは製品や主要機能の根幹を担う
  • ただし、Wasmベースのフレームワークのみで構築された大規模Webサイトはまだ少数
  • 直接Wasm向けにアプリケーションを構築する例も一般的ではない現状

WebAssemblyとは何か

  • 一言で言うとWebAssemblyは言語
  • 「Wasmの速度は?」という問いは言語そのものより実行エンジン依存
  • JavaScript同様、Wasm自体に速度はなく、V8等のエンジン性能が重要
  • 問われるべきは「この言語の構造が現代ハードウェアにどれだけ効率的にマッピングできるか」

効率的なマッピング

  • Wasmはアセンブリ言語に近い抽象度を持つ
  • ただし完全なローレベルではなく、より高水準
  • 大半のアセンブリ言語へ効率的にコンパイル可能
  • WAT(WebAssembly Text Format)で手書きも可能
  • JVMバイトコードと似た設計思想だが、APIが小さく安全性が高い
  • メモリ管理や権限はより厳格で、ホストからの明示的なインポートが必要

コンパイルターゲットとしてのWasm

  • **Rust, C, Zig, Go, Kotlin, Java, C#**など多くの言語がWasmへコンパイル可能
  • Python, PHP, Rubyなどインタープリタ言語もWasm上で動作
  • AssemblyScript, Grain, MoonBitなどWasm専用言語も存在
  • ガーベジコレクタの有無も選択可能(GC対応は最近の進化)
  • ブラウザにはWasmエンジンが標準搭載
  • Wasmtime, WasmEdge, Wasmer等、独立実装も多数存在
  • 単一バイナリ成果物を生成し、ハードウェア非依存で実行可能

セキュリティとその恩恵

  • deny-by-default設計、最小限API、隠蔽された制御フロースタック、リニアメモリで高い安全性
  • 単一プロセス内でプロセス並みの分離を実現
  • CloudflareはV8 Isolateで未信頼コードを高速かつ安全に実行
  • Fermyonはミリ秒未満の起動時間を実現
  • セキュリティが効率や新機能解放につながる
  • RuffleはFlashを安全に復活、PyodideはPythonを安全に実行
  • FigmaはQuickJS(Wasmビルド)でプラグインを安全に実行

移植性と組み込みやすさ

  • Wasmランナーは軽量で多様な環境に対応
  • プラグインエコシステムでZellij, Envoy, Lapce等がWasmを採用
  • JSエンジン環境でWasmがあれば多様なプログラムが利用可能
  • 画像処理、OCR、物理エンジン、メディアツール、DB、パーサ等で活用
  • GodotやFigmaはC++コードをWasm経由でブラウザ対応
  • 言語間の橋渡し用途が主流

速度とサイズの再考

  • ブラウザはJSと同様のパイプラインでWasmを実行
  • 言語やコンパイラの最適化次第で効率向上が可能
  • JITエンジンの特性やメガモーフィック関数の回避も影響
  • ホスト境界のコストやバイナリ肥大化の課題も存在
  • WASI等の標準化で改善が進む
  • Zigは特に小さなWasmバイナリを生成
  • ネイティブ環境でのWasmはスレッドやIOでコスト増
  • 多くの用途で「十分速い」が、極端なパフォーマンス要求には不向き

言語開発と今後

  • Wasm IO YouTubeチャンネルなどで活発な議論・発表
  • 標準化と進化のスピードに賛否両論
  • W3CワーキンググループBytecode Allianceで異なる進行
  • WITやWebAssembly Component Model等、周辺ツールも急速発展
  • 進化の可視性が低く「何も起きていない」と感じる人も多い
  • WasmはJSの完全な代替とはならず、主にライブラリ作者が活用
  • アプリ開発者には内部実装がブラックボックス化
  • フレームワーク(Blazor, Leptos等)経由でWasm利用が進行

まとめ

  • WebAssemblyは多くの分野で現実的な価値を発揮
  • 速度・安全性・移植性を兼ね備えた汎用コンパイルターゲット
  • 直接的な「革命」ではなく、裏方的技術基盤として浸透中
  • 今後も標準化やエコシステムの進化が期待される

Hackerたちの意見

ウェブアセンブリの大きな可能性って、すごいと思うんだ。理論的には、WASMは単一のクロスプラットフォームコンパイルターゲットになれるから、まさにコンピュータサイエンスの聖杯みたいなもんだよね。すべてがウェブアセンブリで動く世界を想像するのは簡単だし、デスクトップ環境やサーバー、日常のソフトウェアアプリケーションまで。そういうのを考えた後に、ウェブアセンブリがFigmaの一部を速くする手助けをしているって聞くと、ちょっとがっかりしちゃうよね。もちろん、それはフェアじゃないけど、WASMに対する期待に応えられるものなんてほとんどないから。開発も委員会方式だから、今の状況ではそれがベストかもしれないけど、物事が進むのが遅いことで有名だしね。
JavaScriptを単一のクロスプラットフォームコンパイルターゲットとして使うこともできるよね。何が違うの?
コンテナをWASIに置き換えない理由はないよ。コンテナって本当にひどいもので、VMにすべきだと思う(WASMの意味でね、「仮想X86でLinuxを動かす」って意味じゃなくて)。ツールがまだ整ってないんだよね。みんなDockerのサポートにまだ囚われてるし。
そうだね、問題は…「理論上」ってことは、WASMが本当に役に立たないなら誰も賭けないってことなんだ。人々はHTML、CSS、JavaScriptを使ってるけど、それはすごく役に立つって証明されてるから。WASMは無駄ではないけど、どうやって人々がそれに親しむことができるの?ほとんどの人にとっては異星のスタックみたいなもんだよ。
まだ見てないなら、[0]を観ることをおすすめするよ。JavaScriptの歴史について、たしか2035年まで説明してるから。 [0] https://www.destroyallsoftware.com/talks/the-birth-and-death...
30歳でママと住んでる天才児みたいに、いつかは潜在能力の話をやめて、結果の話をしなきゃいけない時が来るよね。この場合、理論と実践が合ってないし、WhatWGのボードにいる企業は、自分たちの儲かるアプリストアが、どんなアプリも同じように動かせるプラットフォームに脅かされないようにする利害関係があるって多くの人が指摘してるのを覚えてる。Native Clientが登場して、複雑なネイティブアプリをウェブにコンパイルして、ネイティブの95%の速度で動かせるようになった時のことを思い出す。あれは多くの点で洗練されていなかったけど、今のWebAssemblyよりもよく機能してた。WebAssemblyのもう一つのキラー機能は、ネイティブなウェブ統合だったはず。JSエンジンの仕組みは、JSクラスのインターフェースを説明するIDLがあって、それを使ってC++の実装にバインドするコードを生成するんだ。おそらくそれをWebAssemblyにもバインドできると思う。クロスプラットフォーム、つまりCPUアーキテクチャを越えることはあまり重要じゃないと思うけど、「すべてで動く」って意味なら同意するよ。それに、WebAssemblyの隠れた秘密は、実はJSより速くないってこと。
> WASMは単一のクロスプラットフォームコンパイルターゲットになり得る、それはCSの聖杯みたいなものだね。JVMは1995年から「こんにちは!」と言ってるよ。
> WebAssemblyがFigmaの一部を速く動かすのに役立つと言われるのは、ちょっとがっかりだね。Figmaのようなツールは、実際にはそれがなければ成り立たなかったから。
*純粋な潜在能力 = すぐに壊れそう
またJavaとJVMの話か。
スピードで見落とされがちなのがバイナリサイズなんだ。WebAssemblyはストレージスペースに関して非常に非効率的なんだよね。DSLを使ってる人は、実行を始める前にブロブをダウンロードするのに数秒(場合によってはGodotだと数分)待たなきゃいけない。一方で、JavaScriptはサイズが小さいからダウンロードがずっと速いし、ダウンロード中に実行もできるからね。
もっと言うと、JavaScriptにはすでに大きな標準ライブラリが用意されてるからね。整数を印刷したり、JSONやUnicodeテーブルを解析するためのコードを送る必要がないんだ。
それは状況によるね。高水準のGC言語をWasmGCにコンパイルするなら、JSより大きくなる理由はほとんどないと思うよ。
WebAssembly自体は、ストレージに関してそんなに非効率ではないよ。主にバイナリに伴う通常の膨張が原因だから。例えば、Goのバイナリは、ガベージコレクションを含む完全なランタイムを提供しなきゃいけない。サイズが最優先なら、Cを使って非常に小さなバイナリを生成することもできる。プロジェクト[0]は、ハードウェア、BIOS、DOS互換を含むx86アーキテクチャをエミュレートしていて、圧縮されていないWebAssemblyのサイズは78kB、転送サイズは24kBになる。 [0] https://github.com/s-macke/FSHistory
これは完全に間違ってる。• WebAssemblyはそんなに大きくないよ。基本的にはJavaScriptよりも一般的に小さいけど、JavaScriptはもっと標準ライブラリやランタイムがあるから、比較が不公平になるんだ。Rustみたいな言語を使えば、基本的なオーバーヘッドを10kBくらいに抑えるのは難しくないし、大きなプロジェクトでも100kB以下にできるよ。ただし、UnicodeやCLDRテーブルが必要になると話は別だけどね。トランスポート圧縮を考慮すれば、一般的にJavaScriptと同じようにスケールするよ。Goや.NETを使うと、確かに重いランタイムがあって、1MBか2MBになるかもしれないし、Unicode/CLDRテーブルの必要性にもよるけど、その場合はJSがバンドルサイズや起動時間で圧倒的に勝つだろうね。• JavaScriptはダウンロード中に実行できない。理論的には、投機的パースや限られた投機的実行が可能だけど、そんなことを真剣に試したエンジンはないと思う。WebAssemblyに関しては、ストリーミング中にコンパイルしてインスタンス化できるから、ダウンロードするよりも早い速度で進むことが多いよ。結果的に、同じ条件で比較すると、WebAssemblyはJavaScriptよりも起動がかなり早いんだ。
これに加えて、Godotランタイムの後、ゲームアセット自体もダウンロードしなきゃいけないから、DLCや物理メディアでは意味があったZIPみたいなアーカイブ形式を使うことが多いけど、単一のスプライトにアクセスするために何GBもの大きなダウンロードが必要になるんだ。ブラウザのDOMレンダリングは、リソースを表示される順に優先することがほとんどだからね。それに、WASMゲームランタイムは冗長な2Dや3Dスタック、音声、フォント、harfbuzzなどをバンドルする必要があるのに、ブラウザがすでに持っているネイティブなテキストレンダリング機能を提供していないんだ。全体的に開発者の体験を優先していて、ユーザーの体験が犠牲になってる。
問題じゃないよ。LTO最適化を実行して、全てのシンボルを削除すると、そこそこ複雑なGPUアクセラレーションレンダリングで圧縮2MBが得られるよ(minfx.ai)。
WebAssemblyの標準設計はバイナリサイズの最適化を考慮している。フォーマット自体はかなりコンパクト。でも、ネイティブコードをWasmに移植すると、既存の大きなライブラリがたくさん含まれてしまって、バイナリが大きくなる。ネイティブエコシステムはバイナリサイズの最適化に注意を払ってこなかったけど、JSエコシステムは最初からコードサイズに気を使っていた。
Leaning Technologiesでは、私たちのツールでWebAssemblyを積極的に使ってるよ。WebAssemblyを使うことで、* ブラウザでx86バイナリをJITで実行できる(https://webvm.io) * ブラウザでJavaアプリケーションを実行できる、Minecraftも含めて(https://browsercraft.cheerpj.com) * ブラウザでnode.jsコンテナを実行できる(https://browserpod.io) すごくパワフルなツールだけど、かなりの上級者向けだね。普通のフロントエンドロジックをWebAssemblyでコンパイルするのはあまり意味がないと思うよ。
> 平均的なフロントエンドのロジックをWebAssemblyでコンパイルするのはあまり意味がないよ。なんで? .NET Blazorや他のものはすでにそれをやってるじゃん。私にとっては、これがWASMの全体的な盛り上がりだった。JSを置き換えること。ブラウザでnodeやjavaを動かすことに興味はないし、なんでそんなことをしたいのか分からない。ブラウザの外でそれらを動かせるからね。もちろん、何か使い道があるならそれはいいし、WASMがそれを可能にしてくれるのは嬉しいけど、ほとんどの開発者がそれに関心を持つ理由が本当に分からない。私たちはウェブをブラウジングしたり、ウェブサイトを表示するためにブラウザを使ってるんだ。私にとってブラウザはウェブサイトを表示するためのもので、私はウェブサイトを作るけど、JSは大嫌い。だから、JSなしでウェブサイトを作れるのは素晴らしいことだよ。
Firefoxでbrowsercraftが動かない理由って何かあるの?結局Braveで開いてめっちゃ楽しんだよね、ハハハ。CheerpJがここまで進化してるのはすごいよね。5年か10年前にこのパフォーマンスがあったら、ウェブプラットフォームのいろんなことが違った展開になってたかも。
最近、JavaScriptのビルドツールの多くがRustで書かれてるんだよね。中にはWASMを使ってブラウザで動かせるものもあるし。ReactはJavaScriptのデファクトスタンダードなUIフレームワークだけど、たくさんのWebAssemblyコンポーネントがあるんだ。npmエコシステムも静かにWebAssemblyを取り入れてきてるし、最近のUI関連はWebコンポーネントとしてパッケージ化されることが多いよね。その中にはWASMを使ってるものもあるし。もしWASMが使えなくなったら、多くのものが動かなくなって、JSのフロントエンド界に大きな影響が出ると思う。まだ普及してないのはネイティブWASMのモダンUIフレームワークだね。WASMで動かせる古いものはたくさんあるけど、同じじゃない。ブラウザで動いてるデスクトップUIツールキットみたいなもんだから。ウェブはまだCSSとDOMツリーに縛られてるし、WASMがちょっと弱いのは、ブラウザAPIとJavaScriptを介してやり取りしなきゃいけないからなんだ。これは解決可能な問題だけど、今のところは遅いし、最適とは言えないね。解決策は来てるけど、一晩で変わるわけじゃない。フロントエンドチームがJavaScriptの代わりに他のものを使うには、もっと努力が必要だよ。でも、モバイルフロントエンド開発者がWeb向けにクロスコンパイルするのは増えてきてるね。JetBrainsのCompose Multiplatformは、今はネイティブAndroid/iOSに対応してて、ベータ版でキャンバスレンダリングのWebフロントエンドもサポートしてる。実際、WASMからDOMを操作できるんだ。Rustのフレームワークもいくつかあるよ。KotlinのWASMサポートを使ってブラウザのDOM APIにアクセスするのも試したことがあるけど、そんなに難しくない。ただ、Rustはフロントエンドの作業にはあまり理想的じゃないかも(低レベルすぎて難しい)し、多くの言語には低レベルのブラウザAPIをターゲットにしたフレームワークが不足してるんだ。これを解決するのには何年もかかるだろうけど、今のところ多くのものがWASMにコンパイルできるし、ほとんどのブラウザAPIにアクセスできる感じだよ。多少のパフォーマンスペナルティがあってもね。
> ReactはJavaScriptのデファクトスタンダードなUIフレームワークだけど、たくさんのWebAssemblyコンポーネントがあるんだ。これ、単純に間違ってると思うんだけど、例はある?
あなたはCLIツールとReactを混同してるんじゃない?
私には、Wasmは大きく成功していて、作られた時の目標のほとんどすべてを達成しているように思える。この記事は、Wasmがサポートされている多くのニッチを挙げていて、私自身もWasmをコアコンポーネントとして使ったプロジェクトを何十も展開してきた。私はWasmの大ファンで、最初にEmscriptenの初期バージョンでJSコンソールからmallocを呼び出した時からお気に入りの技術の一つになった。モダンなJSエンジンはほとんど奇跡的に速いけど、Wasmは最高のパフォーマンスを提供し、CPU上で実際に何が動いているかをより高いレベルで制御できる。過去にこれについて書いたことがある。Wasmが本当に不足しているのは、多くの人が予測していたように、JS+HTML+CSSの完全な置き換えになることだと思う。この点については同意せざるを得ない。DOMバインディングの不足が、数年間ずっと重要な欠けている部分と考えられているか、あるいは他の何か、もっと根本的な問題かもしれない。YewのようなWasmを使ったウェブフレームワークを試してみたけど、私には改善をもたらさなかった。ただ、JSとCSSの上に無理やりくっつけたようなレイヤーに感じるだけで、新しいパターンや機能を追加しているわけじゃない。JSイベントの動作の基本的な意味を保たなきゃいけないし、DOMやHTML要素システム全体を維持しなきゃいけないし、その上にフレームワークが導入する新しいものにも対処しなきゃいけない。他のフレームワーク、例えばBlazorは試してないけど、私はやっぱりJSを書きたいと思ってしまう。これは私がReactやSvelteを使ってウェブアプリを作る経験が深いからかもしれないけどね。とにかく、Wasmは成功した技術だと強く感じてる。思っている以上に多くの場所で、静かにその役割を果たしていると思う。それがWasmの成功の証だと思う。
それは、ノートパソコンにLinuxをインストールするようなものだね。ノートパソコンを買うとき、結局Windowsのためにお金を払うことになるから。
> それが本当に不足しているのは、多くの人がWebアプリを作るためのJS+HTML+CSSの完全な置き換えになると予測していた点だね。私は、そんなことがすぐに起こらないことを願ってる。YouTubeやSpotifyは理論的には今すぐにWasmを使ってキャンバスに描画できるけど(かなりの開発努力が必要だけど)、それだと現在DOMのおかげでできること(スクレイピングや広告ブロッカーなど)が難しくなったり不可能になったりする。
私は、Wasmを使ってウェブアプリ全体を構築するのが有望なアプローチだとは思わなかった。DOMとインタラクションできるようにするだけじゃダメなんだ。こういうDOMインタラクションやアプリケーションロジックを行うための適切な高水準言語も必要だよ。JSはその目的には悪くないし、WASMにコンパイルされるものでJSよりもずっと良いものを見つけるのはかなり大変だと思う(tsやsvelteみたいにね)。JSなしのウェブアプリケーションの唯一の現実的な道は、ブラウザのレンダリングパスを完全に放棄して、すべてをキャンバスに描画することだろうね。デスクトップ向けに設計されたUIツールキットを使う実験もあるけど、それもニッチな解決策に過ぎないと思うし、広く使われることはないだろうね。HTML/CSS/JSはUI開発の共通語になっていて、デスクトップアプリケーションにも浸透してきてる。なんでその流れが逆転すると思う?
記事はWasmをアプリが構築されるフレームワークのように評価しているみたいだけど、実際にはそうじゃなくて、CPUの最適化やブラウザ内のネイティブコードの再利用を可能にする直交的な技術なんだ。その期待に反して、まだベアメタルレベルのパフォーマンスやエネルギー効率には達していないけど、大成功を収めているよ。例えば、C++ライブラリに基づいたブラウザ内のオーディオタイムストレッチ [1]。もしこれがJSで実装されていたら、(a) 同じパフォーマンスや (b) ネイティブアプリへのソースコードの移植性を提供することは不可能だっただろうね。[1] https://bungee.parabolaresearch.com/change-audio-speed-pitch
ウェブアプリ構築について: 「何年も前から重要な欠けている部分とされているDOMバインディングの不足が続いているのか、他に何かもっと根本的な問題があるのかもしれない。もっと根本的には、すべてのフロントエンド開発者がほぼ同じJS言語(Typescriptも含む)を使っていて、すべてのモジュールがほぼ相互運用可能なんだ。WASMはコンパイルターゲットだから、開発者は異なる言語やツール、ライブラリを使っているかもしれない。どれかがクリティカルマスに達しているかもしれないけど、すべてを影に隠す巨大な存在(JS)がある。ウェブアプリの特定の部分は他の言語で書けるけど、ユーザーとの間にはまだJSのフロントエンドがあって、GUIは大きなアプリになることもある。最適化を目指したシステムに見えるね。バックエンドについては、RustやWASMをターゲットにできる他のコンパイル言語で書くなら、WASMにコンパイルする理由は何なの?ネイティブコードにコンパイルしないの?」
ここ数年、WebAssemblyに積極的に関わってきた者として、WASMベースのフレームワークを発表しようとしているんだけど、こんなことがあったよ。 - エコシステムは最初は急速に進化したけど、その後は遅くなった。これが原因で、特にWASIやコンポーネントモデルのようなものの採用に問題が出た。多くの人が自分のやり方やサードパーティを使っていたから、今や新しいものに書き直さなきゃいけない状況なんだ。まだ完全にサポートされているわけじゃないのに。 - 「開発」の仕方が原因で、多くのものが分散していて同期されていないし、使っているエンジンによってサポートレベルもバラバラ。これが開発者の混乱を招いている。記事を読んで、仕様を読んで、GitHubのイシューを読んで、気づいたら深夜2時にランダムなRustコードを3つのリポジトリで読みながら、他人のフォークに頼れるかどうかを考えている。そんなはずじゃなかったのに。 - これらが組み合わさると、LLMにとってもさらに混乱を招く。彼らは古いデータでトレーニングされているから、しばしば物事を誤解したり、もう存在しないものを探したりする。人間と同じようにね。 - そして、私が思う一番大事なことに焦点を当てよう:JavaScript/TypeScriptのサポート。これは広く採用される仲介技術にとっての聖杯だよ。可能ではあるけど、ハックの上にハックを重ねて、次のユーザーが全てを壊さないことを祈るような状況。ユーザーが自分の使っているものを持ち込めるようになるまで、移行する価値はあまりないし、あらゆる組み合わせやニーズのために自分で配線を書くのは無駄だと思う。Webコンテナで一歩前進したけど、その頃には多くの人がBunに移ってしまった。
ツールがWebAssemblyの足を引っ張ってる。WebAssemblyアプリケーションのデバッグはすごく難しいし、ソース言語によっては、まだprintfデバッグのような体験から抜け出せてない。ChromeのDWARFプラグイン(これだけ、他では使えない)も2023年から更新されてないし。言語によっては、.wasmファイルを生成するのも一苦労で、関数のインポート/エクスポートのセットを作る必要がある。単に「-arch=wasm」ってわけにはいかない。GCサポートは今はあるけど、「はい、でも」という感じで、全てのGC要件をサポートしているわけじゃないから、.NETのようなエコシステムは自分たちのを出さなきゃならない。最後に、WITがCOM/CORBA/gRPCの別の試みをしようとしてる。
> 言語によっては、.wasmファイルを生成するのも一苦労で、関数のインポート/エクスポートのセットを作る必要がある。単に「-arch=wasm」ってわけにはいかない。 「WASMコンポーネントモデル」がこれを解決するんじゃない?私はRustでWASMアプリランナーをハッキングしていて、基本的には「コンポーネント」にコンパイルされた小さなアプリを読み込むもので、使ったり作ったりするのは結構簡単そうに思えるんだけど。
これに賛成。ツールは10年経ってもまだ整ってない。 - 既存のCコードベースをWebAssemblyにコンパイルするための主なツールチェーンはEmscripten。まだ技術デモの起源から抜け出せてなくて、コンパイラフラグやジャンクなポリフィルの巣窟になってる。全ての実装が半分完成した状態で少なくとも3つある。セマンティックバージョニングに従ってないから、ポイントリリースごとに壊れる変更が出やすい。 - 「モダン」なツールチェーンであるwasi-sdkは、もっとベアボーンな状態。使えるレベルにはなってきてるけど、プリコンパイルされたlibcとlibc++が`-O3`を使っているから、自分では使えない。Emscriptenはsysrootを再コンパイルしてキャッシュして、`-Oz`を使うように指示できるから。これでコードサイズが増えてしまう。すでにかなり大きいのに。 - LLVMは最適化されたWebAssemblyバイトコードを出力するのがまだまだ苦手。 - エンジンもWebAssemblyバイトコードを最適化された機械コードにコンパイルするのがあまり得意じゃない。 - デバッグ情報は、あなたが言ったように、完全に混乱してる。 - RustのWebAssemblyツールは今や生死の境をさまよってる。rustwasmのGitHub組織は、数年間の活動停止の後、2025年中頃に「日没」される予定。 - 2026年の今、JavaScriptからWebAssemblyモジュールをクロスプラットフォームでインポートする公式な方法はまだない。ブラウザにデプロイしてViteや生のESモジュールを使う場合、`WebAssembly.instantiateStreaming(fetch(new URL('./foo.wasm', import.meta.url)))`を使ってトップレベルのawaitを食べることができる。Viteは`new URL('...', import.meta.url)`パターンを認識して、ビルド出力にアセットを含めるけど、他のバンドラー(例えばRollupやesbuild)はそうじゃない。Node上ではこれができない。なぜなら、`fetch`がローカルファイルには使えないから。ほとんどの人は諦めて、WebAssemblyバイナリを巨大なBase64文字列として埋め込むことになる。これでファイルサイズが33%増えて、圧縮率も大幅に下がる。 - マルチスレッドのWebAssemblyが欲しいなら、`SharedArrayBuffer`にアクセスするためにCOOP/COEPヘッダーを設定する必要がある。GitHub Pagesはこれを許可していないけど、これは3番目に多くのアップボートを受けている機能リクエストだ。サービスワーカーをインストールするジャンクな回避策があるけど、その回避策がPWAとどう絡むかは全く不明。WebAssemblyが初めて出荷されてからの8年間で、ツールの状況が「技術デモ」を超えて進化していれば、もっと多くの人が使っていただろう。
一番の失敗は、UTF-8文字列をファーストクラスの市民として扱わなかったこと。二番目の失敗は、直接メモリマッピングを許可しなかったこと。セキュリティシステムに反するのは分かるけど、ホストにピクセルを一つずつコピーしなきゃならないなら、効果的じゃないよね。三番目の失敗は、GCオブジェクトを追加したときに、オブジェクトのプロパティをホストから読み取れないようにしたこと。
私にとって一番の問題は、WASMで会社を運営している人たちの動画や記事がたくさんあるのに、サンプルコードがfn(i32, i32) i32みたいなものばかりだってこと。言語間の相互運用性やWASIのような事前定義されたAPIがまだ整ってないから、使うのが厳しいんだよね。もちろん、WASMでクレイジーなことはできるけど、初期のRustみたいなもので、今でもGoとして宣伝されてる感じ。
ちょっと気になるのは、asm.jsはどうなったの?WASMにやられちゃったよね。ある意味、これは良いことだよ。WASMは「より良い」解決策で、正式なバイトコードマシンの説明だから。でも一方で、asm.jsはDOMとの相互作用やガーベジコレクションの統合についての議論に関して、同じ制限がないから、JS VMにしっかりと留まっていればこれらのことは無料で得られるんだ。基本的に、ある意味では優れたアイデアだったんだよね。JSの最適化から恩恵を受けつつ、良いコンパイルターゲットとなるサブセットを定義して、JS VMがすでにかなり最適に動作することが分かっている。だからサブセットを定義する以外に特別な作業は必要ない。逆に、引き継ぐJSの制限があることは確かだし、たぶん「バイナリ」はWASMよりちょっと大きいかも。(でも、たぶん圧縮しやすいと思う。)良いニュースは、このアプローチをまだ使えるってこと。ただ、誰もやってないけどね、WASMが注目を奪っちゃったから。これが良いことなのか悪いことなのかは分からないけど、考えるのは面白いよね…例えば、リソースを新しいランタイムに振り分ける代わりに、asm.jsを完全に採用していれば、今の状態にもっと早く到達できたかもしれないってこと。