- WebAssemblyは2017年の初公開以降、C/C++ などの低水準言語の実行を支援しながら発展してきたが、依然としてWebプラットフォームでは第二級言語として扱われている
- Web APIと直接相互作用できるのはJavaScriptだけであり、WebAssemblyではそのために複雑な**JSバインディングコード(glue code)**を書く必要がある
- この構造はロード手順の複雑さ、性能オーバーヘッド、言語ごとのツールチェーン分断などにつながり、開発者体験を損なっている
- Mozillaはこれを解決するためにWebAssembly Component Modelを提案し、JSなしでも標準化された方法でWeb API呼び出しとモジュールロードを可能にしようとしている
- このモデルが定着すれば、WebAssemblyはブラウザ内の第一級実行環境として位置づけられ、一般の開発者でも容易に活用できる基盤が整う見込みだ
WebAssemblyが第二級言語として扱われる理由
- WebAssemblyはJavaScriptを通してしかWebプラットフォームにアクセスできず、Web APIを直接呼び出す権限がない
- JavaScriptは
<script>タグで簡単にロードできるが、WebAssemblyはJS APIを使った手動のロード処理が必要
WebAssembly.instantiateStreaming() などの複雑なAPI呼び出しを経る必要があり、開発者はこれを暗記するかツールで自動化しなければならない
- esm-integration提案は、JSモジュールシステムを通じて
.wasmファイルを直接 import できるようにし、ロード手順を簡素化する
<script type="module" src="/module.wasm"></script> の形で直接ロード可能
Web APIアクセスの制約
- JavaScriptでは
console.log("hello, world") の1行で済む作業が、WebAssemblyではJSメモリアクセス、文字列デコード、関数ラッピングなどの複雑な手順を要する
- WebAssemblyは
consoleオブジェクトやDOMにアクセスできないため、JS側でメモリ共有と関数 import/exportを通じて間接的に呼び出す必要がある
- この過程で生成される**バインディングコード(glue code)**は言語ごとに異なり、
embind、wasm-bindgen のようなツールで自動生成される
- しかし、ビルドの複雑化、ランタイムオーバーヘッド、言語間の非互換性といった問題が生じる
WebAssemblyが第一級言語になれていない技術的要因
- コンパイラ統合の難しさ: 各言語のコンパイラは、JSおよびWebプラットフォーム統合コードを個別に生成しなければならず、再利用できない
- 標準コンパイラの非互換性:
rustc --target=wasm で生成したファイルは、ブラウザでそのまま実行できない
- プラットフォーム統合を実装した非公式ツールチェーンを別途インストールする必要がある
- ドキュメントエコシステムの偏り: MDNなどのWeb文書の多くはJavaScript中心に書かれており、他言語の利用者にとって参入障壁が高い
- 性能問題: JSバインディングを経由したDOM呼び出しは、直接呼び出しに比べて45%の性能低下が発生する
- Dodrioフレームワークの実験では、JS glueを取り除くとDOM変更の適用時間が半分に減少した
- JavaScript依存: WebAssemblyを実務で活用するには結局JSを理解する必要があり、これは**抽象化の漏れ(leaky abstraction)**の問題につながる
WebAssembly Component Modelの登場
- WebAssembly Component Modelは、複数の言語とランタイムで共通利用できる標準化された実行単位を定義する
- Web APIアクセス、モジュールロード、リンク処理をJSなしで直接実行できる
- さまざまな言語で生成でき、ブラウザやWasmtimeなど複数のランタイムで実行をサポートする
- **WIT(Interface Description Language)**を通じて必要なAPIを宣言し、コンポーネント内部から直接呼び出せる
- ブラウザは
<script type="module" src="component.wasm"></script>でコンポーネントを直接ロードし、JSなしでWeb APIバインディングを自動処理する
JavaScriptとの相互運用
- Component Modelはハイブリッドアプリ構造もサポートする
- 例: 画像デコーダをWebAssemblyで書き、JSから
import { Image } from "image-lib.wasm"; の形で呼び出せる
- JSはWebAssemblyコンポーネントを通常のモジュールのように import/exportして利用する
今後の展望と参加
- MozillaはWebAssembly CGと協力してComponent Modelの標準化作業を進めており、Googleも検討段階にある
- 開発者は Jco や Wasmtime を通じて、ブラウザまたはCLIで試すことができる
- このモデルが定着すれば、WebAssemblyは**「パワーユーザー向け機能」から一般の開発者も活用できるWeb技術**へと拡張される可能性がある
4件のコメント
これは単なるMozilla的な希望的観測に近いでしょう。フロントエンドは市場の反応という辺縁系から構造的に抜け出すことができません。WebAssemblyの登場と同時に Doom 3 が移植されましたよね。DOM は現代のブラウザではすでに軽量なプロキシオブジェクトに変わって久しく、現代 CPU の JavaScript 専用命令セットや、シングルコアの量子的な限界を考えれば、このようなアプローチが市場価値の面で優位に立つことは永遠にないでしょう.
Electron の中で動く WebAssembly バイナリに何の意味があるのでしょうか。これは単なる別の GitKraken CLI、あるいは Rust 移植の名声狙いのように見えます。
他はともかく、
<script type="module" src="/module.wasm"></script>のように wasm モジュールをファイルとして挿入する方式は興味をそそられますねそれに、WebAssemblyの参入障壁が高いという主張は荒唐無稽だとはっきり言っておくべきでしょう。単に、その必要性が対価を払う意思より低いだけです。高速で小さなフットプリントを求めながら DOM と CSS を使いたい? これはいったい何のブラックコメディですか。
Hacker Newsのコメント
WebIDLをWebAssemblyでサポートしようとしていた当初の目標を捨てて、別のIDLを作ると言い出し、しかもDOMアクセスの欠如を問題視しなかったのは残念
市場の現実は理解しているが、失われた時間が惜しいという思いは消えない
関連リンク: commit記録, stringref回顧, ACM記事
その後、目標が2つ追加された。1つは非Web API対応、もう1つは言語間相互運用性だった
WebIDLはJSとWeb APIの和集合なので表現力は高いが、こうした目標と衝突する概念が多かった
そのためcomponent interfaceは表現力を下げる代わりに、はるかに移植性の高い共通部分アプローチを選んだ
個人的にはDOMアクセスは重要だと思うが、Wasm CGは優先度の高い仕事で手いっぱいだった
今回この記事を書いたのは、この問題を今でも覚えていて、作業を続けるつもりだと伝えたかったからだ
ツールチェーンとビルド工程が複雑すぎて、使うたびに認知的負荷を感じる
パフォーマンスはglueなしのほうがはるかに良いが、そのぶんリスク要因も大きい
component modelが新たな複雑さを持ち込まないことを願うが、複数言語の例を見るとすでにかなり混乱している
特に Goの例 を見ると生成ファイルが多すぎて、開発者としてはツールの単純化が切実に必要だ
今は複雑さをなくしているのではなく、ただ別の場所へ移しているだけに見える
wasm component仕様が変わり続けたため、churnが多かった
目標はWeb開発者がWITを直接書かず、Web APIをライブラリのように使えるようにすることだ
ただし、まだ先は長い
たとえばテキスト共有、メディア共有、アプリケーション共有などに分ければ、セキュリティも向上し、小規模チームがブラウザ代替を作ることもできる
しかし巨大なWeb APIとCSSの規模がブラウザ独占を支える要素なので、こうした試みは難しそうだ
WebAssembly registryを標準化して、コンポーネントを簡単に組み合わせられるようにしてほしい
結局のところ、Webは分散OSの定義を作る過程なのだ
概念からコード例までよく整理されている
JSエコシステムでは StarlingMonkey, ComponentizeJS, jco の3プロジェクトが中核だ
現時点で最も成熟したツールチェーンはRustだが、LLVMベース言語(C/C++, Go, Pythonなど)への対応も徐々に良くなっている
WebAssemblyの目標は、ローカルツールチェーンに自然に溶け込むコンパイルターゲットになることだ
依然として言語ごとのglueコードや2つのランタイムモデルを理解しなければならないなら、WebAssemblyはまだ「極端な状況でしか使わない道具」のままだろう
本当に変化を起こすには、一般的なビルド経路を単純化しなければならない
Component Modelでこの部分がどう扱われるのかは不明瞭だ
DOMはブラウザごとに異なり、ページ読み込みごとに機能も変わる
JSブリッジ層ではpolyfillを簡単に適用できるが、WITインターフェースではランタイムのメソッド検出やpolyfillが難しい
性能だけでなく、エコシステムの柔軟性も重要だ
JSのglueコードを自分で管理したり、自動生成ツールに頼ったりするのは大きな後退に感じる
Dodrioの実験でglueを省いて45%のオーバーヘッド削減を得たのは印象的だ
ただ、WebAssembly Component ModelがWeb APIと直接やり取りするとき、メモリ管理がどうなるのか気になる
Wasm GC提案がDOM参照の保持に使われるのか、それとも依然としてJS GCに依存するのか知りたい
Wasmが真の第一級市民として定着することを期待している
ただ、現状のIPCはまだ非効率で、メモリページ単位の転送のような方式が必要だと思う
誰でも複雑なプログラムを自分のコンピュータで実行できるようにするなんて、セキュリティ的には狂気じみたアイデアだったが、実際にそうしてきた
JSのおかげで20年間にわたり無数のブラウザセキュリティバグを経験したが、今では設計原則と緩和策が定着している
なのに今になって、また別の危険な実行パラダイムに置き換えようとしているのは、皮肉でもあり美しくもある
モバイルOSはデスクトップよりずっとうまくやっている
エンジニア中心に設計されており、作者に優しい基本ワークフローがない
それでも、こうした問題を気にかける人たちがまだいるのは幸いだ
DOM APIを1:1でマッピングするために、2倍速い文字列処理だけのために過剰なエンジニアリングをしているように見える
WebGL2, WebGPU, WebAudioのようなAPIでは、JS shimのコストはすでにごく小さい
本当の問題はGPUバッファコピーのような部分で、component modelはそこには役立たない
WebGL2やWebGPUで数万回のdraw callをテストしたベンチマークを見てみたい
性能だけでなく、開発者体験(DX) の改善も重要だ
今は始めるのが難しすぎて、誰もが専門家にならないと恩恵を受けられない
ネイティブアプリ並みの効率で競争できるなら、Webの未来にとってビジョンのある変化だ
コーディングエージェントの時代には、彼らが言うDX改善はもはや重要ではない