ハクソク

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

WebAssemblyをウェブ上の第一級言語にする

概要

  • WebAssemblyは進化を遂げてきたが、依然としてWebプラットフォームとの統合不足が課題。
  • JavaScriptがWebの第一級言語であるため、WebAssemblyは二級市民的扱いを受けている現状。
  • WebAssembly Component Modelの提案により、直接Web API利用やクロス言語連携の可能性が拡大。
  • 開発者体験の向上普及拡大のためには、さらなる標準化とツール整備が鍵。
  • MozillaやGoogleなどが協力して仕様策定・実装を進行中。

WebAssemblyの現状と課題

  • 2017年の初リリース以降、WebAssemblyは多くの機能拡張を実現
    • 共有メモリ、SIMD、例外処理、GCサポートなど多岐にわたる
  • C/C++などの低レベル言語には最初から適合し、多様なアプリケーション開発を可能に
  • JavaScriptとの連携が必須であり、WebAssembly単体でWeb APIを直接利用できない現状
  • 開発者体験の複雑さが普及の妨げ
    • JSの“scriptタグ”による簡単なコード読み込みに比べ、WasmはJS API経由での手動ロードが必要
    • Web API利用時は“バインディング”や“グルーコード”の自動生成・手動記述が不可避
  • 言語ごとに異なるバインディング生成が必要で、ビルドプロセスも複雑化

WebAssemblyが“二級市民”である理由

  • Webプラットフォームのスクリプト層構造
    • JavaScriptはWeb APIへ直接アクセス可能
    • WebAssemblyはJavaScriptを介さないとWeb APIにアクセスできない
  • JavaScriptの特権機能
    • コードの読み込みの容易さ
    • Web APIの直接利用
  • Wasmの読み込みが煩雑
    • scriptタグ非対応
    • 手動でのAPI呼び出しが必要
  • Web API呼び出し時のグルーコード負担
    • 文字列や構造体のエンコード・デコード処理
    • ランタイムコスト発生
    • RustやC++など言語ごとに異なる対応が必要

開発者体験の壁

  • WebAssemblyの導入は“高い壁”
    • JavaScriptは段階的な学習曲線
    • WebAssemblyは初期段階から複雑な統合作業が必要
  • 標準コンパイラではWeb向けWasm生成が困難
    • 公式ツールチェーンではWeb API統合のためのJS生成がされない
    • サードパーティ製ツールの利用が必須
  • WebのドキュメントはJavaScript前提
    • JSを知らないとWeb API活用が困難
    • 言語ごとのドキュメント翻訳は非効率
  • Web API呼び出し時のパフォーマンス低下
    • JSグルーコードのオーバーヘッド
    • DOM操作時のベンチマークで45%高速化の実例あり(グルーコード省略時)
  • JavaScriptレイヤーの知識が必須
    • 抽象化が“漏れる”ため、結局JSの知識が必要
    • 開発者の負担増加

WebAssembly Component Modelの提案

  • 標準化された自己完結型実行アーティファクト
    • 複数言語・ツールチェーンでのサポート
    • Wasmコードの読み込み・リンク処理を自動化
    • Web API利用を直接サポート
  • WebAssembly Componentsの特徴
    • 高レベルAPIを低レベルWasmコードで実装
    • 複数言語から生成・実行可能
    • クロス言語連携・再利用性向上
    • Web APIへの直接アクセス
  • WIT(WebAssembly Interface Types)によるAPI仕様
    • 例:Console APIの直接インポート
    • Rust等の言語からネイティブに利用可能
    • scriptタグから直接コンポーネントをロード可能
  • ハイブリッドアプリケーションにも対応
    • JavaScriptとWasmコンポーネントの相互利用
    • 例:画像デコーダーコンポーネントのJSからの呼び出し

次のステップと展望

  • MozillaやGoogleが中心となり仕様策定・実装を推進
    • JcoやWasmtimeなどのツールで試験運用が可能
    • 仕様策定リポジトリで開発進行中
  • 開発者・コミュニティからのフィードバック歓迎
  • 今後の展望
    • “パワーユーザー向け”から“全開発者向け”への進化
    • WebAssemblyの真の普及とWeb開発の多様化推進

著者:Ryan Hunt

https://eqrion.net/
Ryan Huntの他の記事も参照

Hackerたちの意見

これ、もしインターフェースタイプの人たちがWebAssemblyでのWebIDLサポートの初期の問題提起を放棄せずに、また別のIDLを作るのに夢中になってなければ、5年前に起こってたことかもしれないね。「DOMアクセスが問題じゃない」とか言ってさ。市場の現実がそうさせたのは理解できるけど、やっぱり失った時間がもったいないなと思う。遅れてもやらないよりはマシかな。
元々のインターフェースタイプの提案に少し関わってたけど、それがコンポーネントモデルになる前のこと。追加された2つの目標は、1. 非Web APIのサポート 2. 限定的なクロスランゲージの相互運用性。WebIDLはJSとWeb APIのユニオンで、表現力はあるけど、これらの目標と矛盾する概念が多い。コンポーネントインターフェースは、表現力は劣るけど、もっとポータブルな交差的アプローチを取ってる。個人的にはDOMアクセスが大事だと思ってるけど、Wasm CGはもっと優先度の高いことに忙しいみたい。この記事を書くことで、少なくとも何人かはこれを忘れてないし、まだ取り組むつもりだって言いたかった。
stringrefが復活してほしいな。
WASMの崖って本当に存在するよね。使おうとするたびに、ツールチェーンの複雑さやゼロから何かを作る過程で、すでに認知的な負担を感じちゃう。ツールを更新したり、最新のものを調べたり、ツールをもっと理解したりしなきゃいけないんじゃないかって心配になる... それが改善されるといいな。グルーなしのパフォーマンスの差はすごいけど、全然驚かない。これがWASMでクールなことをしようとする時の明らかな足元をすくう要因だって、いつも警告してることの一つなんだ。コンポーネントの件で気になるのは、新たな複雑さをどう避けるかってこと。いろんな言語で実装してる例を見てると、どうなるかちょっと怖くなる。まだ初期段階で明確な標準もないから、物事がまだ整理されてないのは仕方ないかな。Goの例(https://component-model.bytecodealliance.org/language-suppor...)は、ファイルを生成するとちょっと狂ってる。消費者にとっては体験が良くなるはずだけど、コンポーネント開発者としては、ツールや出力がもっと扱いやすくなってほしいな。これはDOMのグルーやWeb APIとのやり取りなしのハッピーパスだから、どれだけ複雑になるんだろう?結局、複雑さを排除するんじゃなくて、移すだけの懸念だと思う。
多くのツールがまだ初期段階だってことには同意するよ。WASMコンポーネントの仕様が変わる中で、いろいろな変動もあったしね。私たちの目標としては、ほとんどの場合、ウェブ開発者がWITを書く必要がなくて、Web APIをライブラリのように使えるようにすることなんだけど、まだ初期段階だね。
これは正しい方向だと思う。もう一つ重要なのはGCの統合だね。GoやC#みたいな多くの言語は、GCのせいでWASMではうまくいかない。さまざまなGC機能が不足してるから、GCを一緒に持っていかなきゃいけないんだ。
Goみたいなランタイムをバンドルするか、もし可能なら安全な方法でクロスウェブキャッシングを復活させる必要があるかもね。
今日の新しい標準は、クリーンでシンプルに使えることを気にしてないよね。基本的な例を動かすために必要なJSのボイラープレートを最大化してる。今のすべては「エンジニア」のために設計されてて、「著者」のためじゃない、フレンドリーなデフォルトのワークフローもないし。まだこれを気にしてくれてるのは嬉しいけど。
ウェブって本当に面白いよね。誰でも自分のマシンで複雑なプログラムを動かせるっていう、一見狂った提案から始まったんだから。しかも、それが本当に狂ってたってことが分かった。JavaScriptによる深刻なブラウザのセキュリティバグが20年も続いたし。無駄だったとは言わないけど、やっぱりクレイジーだった。そして、今や正しい設計原則と対策が整いつつあって、JSエンジンの0-dayも高くて珍しくなってきたのに... それを全部引き剥がして、さらにリスキーな実行パラダイムに置き換えようとしてる。怒ってるわけじゃないけど、なんか美しいよね。
WASMの実行がJSよりリスクが高いのはなんで?
明らかにサンドボックスを壊すようなブラウザ機能、例えばWebUSBを追加したいって人たちがいたときだけ怒ったよ。WASMはどうやってこれを壊すの?
>20年以上にわたってJavaScriptによって引き起こされた深刻なブラウザのセキュリティバグがあるけど、あなたはJavaScriptという言語とブラウザAPIを混同してるかも。JavaScript自体は不安定ではなく、長い間そうではなかった。通常は、それがインターフェースするものがセキュリティホールを引き起こすんだ。まだ多くの人がJavaScriptをDOMやブラウザAPIなどの周りのものと混同しているみたいだね。
ブラウザで_どんな_言語でも動かせるようになったらいいな。WASMはその第一歩として素晴らしいね。
インターネットエクスプローラーは、Windows Script Hostが実行できるどんな言語でもサポートしてた。デフォルトではJScriptとVBScriptだったけど、Python、Perl、Ruby、Luaなどのサードパーティ製エンジンもあった。2019年にVBScriptが無効になると発表されたから、今は無効になってるかもしれないね。
この記事は「WebAssemblyの壁」のフラストレーションを完璧に捉えてる。JSのグルーコードを書いたり、オペークな生成ツールに頼ったりするのは、パフォーマンスの良いモジュールを出したいときには大きな後退に感じる。Dodrioの実験でJSのグルーをスキップすることで45%のオーバーヘッド削減ができたのはすごい。でも、DOMみたいなWeb APIと直接やり取りする時のWebAssemblyコンポーネントモデルのメモリ管理の影響が気になる。もしWasmコンポーネントがJSを完全にバイパスしてDOMを操作するなら、ガベージコレクションの境界はどうなるの?コンポーネントモデルは最近追加されたWasm GC提案に依存してDOMの参照を生かしているのか、それともまだ裏でJSエンジンのガベージコレクターを暗黙的にトリガーしているのか?Wasmが本当に一級市民として扱われるようになるのが楽しみだね。
これは素晴らしいステップだね。これによって「正しい」やり方のためのより多くの規約が強制されるし、シンプルなメカニズムが提供されるから。WebAssemblyコンポーネントに関しては、Webコンポーネントが存在するから定義が曖昧になっちゃうので、別の名前にしてほしかったな。オープンソースのグルーピング名は残念ながらすごく難しい。みんな言葉の使い方や広い意味の理解が違うから、こういう重複がよく起こる。LLMが仕様を監視することで、全体のエコシステムを広く見ることができるようになれば、改善されるかもしれないね。
「ファーストクラス」という言葉が重要なのは、ほとんどの開発者がピークパフォーマンスのためにプラットフォームを拒否するわけではなく、摩擦のために拒否するからなんだよね。もしハッピーパスでも言語特有のグルーや生成されたシム、二つのランタイムのメンタルモデルが必要なら、WebAssemblyは痛みが極限に達したときだけ手を伸ばすものになっちゃう。実際に認識を変えるのは、単にベンチマークが良くなることじゃなくて、つまらない道を簡単にすることだと思う。普通のツールチェーンでコンパイルして、自然にWeb APIをインポートできて、普通のウェブアプリを作るためにパートタイムのバインディングエンジニアにならなくて済むようにすることが大事なんだよね。
WebAssemblyコンポーネントが大好きで、これは素晴らしい進展だと思う。でも、みんなが巨大なOSサイズのWeb APIを分解する絶好のチャンスを見逃してる気がするんだ。もっと小さな標準的なサブセットに分けて、情報の提示とアプリケーションを強制的に混ぜないようにすべきだと思う。例えば、以下のようなサブセットが考えられるね: - (主にテキストの)情報共有 - メディア共有 - 小さな標準インターフェースを持つアプリケーション共有(WASI 2とか、もっと良いのはグラフィックスを含むもの) - ネットワークを使った複雑なアプリケーション共有 巨大なWeb APIの小さなサブセットがあれば、セキュリティの状況が良くなるし、小さなグループが情報共有やメディア、アプリケーション共有の「ブラウザ」代替を作るのも現実的になると思う。でも、Web API(やCSSなど)の極端なサイズがブラウザの独占を守っている主な要因の一つだから、これが追求されることは少ないだろうね。さらに、標準的なWebAssemblyレジストリを作って、フルサブセットを実装しなくてもコンポーネントを簡単に組み合わせられるようにするのもいいかも。WebAssemblyコンポーネントはすべての依存関係を追跡してるのかな?巨大なモノリシックAPI、例えばDOMが利用可能だと仮定するのかな?君たちがやってることは、本質的には分散オペレーティングシステムの定義を作ってることなんだよね(ウェブが本質的にそうだから)。それを設計することで、人々が巨大なAPIを実装しなくてもクライアントを作れるようにできるはずだよ。