「第4のブラウザ言語」WebAssemblyが変えるフロントエンド開発

2024年7月23日

執筆

山内 直

有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)に所属するテクニカルライター。出版社を経てフリーランスとして独立。ライター、エディター、デベロッパー、講師業に従事。屋号は「たまデジ。」。著書に『Bootstrap 5 フロントエンド開発の教科書』、『作って学べるHTML+JavaScriptの基本』など。

 

監修

山田 祥寛

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。
主な著書に「独習」シリーズ「これからはじめるReact実践入門」「改訂3版 JavaScript本格入門」他、著書多数

「新発見!フロントエンド技術の今」の連載。第9回のテーマは第4のWeb言語と称される「WebAssembly」です。

WebAssemblyとは

WebAssembly※は、第4のWeb言語と称される、Webアプリにおけるフロントエンド高速化の仕組みです。フロントエンドの世界では、HTML、CSS、JavaScriptを使っての開発が一般的ですが、その4番目の言語がWebAssemblyというわけです。WebAssemblyの正体を探っていく前に、まずは、その登場に至った背景を見ていきましょう。
(※):AssemblyをASMと略することから、WebAssemblyはWASMと呼ばれることもあります。

▲WebAssembly登場の背景

JavaScriptには性能上のボトルネックがある

フロントエンド開発におけるプログラミング言語といえば、第8回でも紹介したJavaScript(ECMAScript)です。JavaScriptでは、言語仕様の強化が継続的に行われており、さらにV8をはじめとする実行エンジンの高性能化に伴い、利用の幅も広がっています。Webアプリのフロントエンド部分の開発はもちろん、昨今では、サーバサイドアプリの開発、ビジネスアプリ、ゲーム、マルチメディア、AI、数値計算の分野などなど、至る所でJavaScriptが活用されています。

そのようなJavaScriptですが、手軽に複雑な処理が記述できる反面、動的型付けのインタプリタ型言語であることから、即時性や実行速度に難もあります。実行エンジン側でもさまざまな工夫でそれらを克服しようとしていますが、それでも根本的な解決には至っていません。特に速度や即時性が重要なゲームやマルチメディア分野ではなおさらと言えます。

ブラウザ外の経験と資産を生かしにくい

フロントエンド開発はHTML、CSS、JavaScriptが中心になることから、ブラウザ外など他分野の開発と分断が起きやすいといわれます。サーバサイド開発はNode.jsなどの登場によってJavaScriptが利用される局面が増えてきているとはいえ、JavaやC#、PHP、Python、Rubyといったプログラミング言語が依然として中心です。特に、ゲームやマルチメディア分野は、速度や効率を重視するためにC/C++などの静的型付けのコンパイラ型言語を用いるのが一般的です。

JavaScriptの高機能化に伴い、ブラウザ外の経験や資産をフロントエンドに持ち込みたいと考えると、JavaScriptの習得や移植の必要に迫られます。JavaScriptは比較的習得しやすい言語とはいえ、学習コストはゼロではありません。できれば、ブラウザ外の経験や資産を生かしてフロントエンドも開発したいという思いは出てくるでしょう。

WebAssemblyはWeb標準の技術

このような背景を受けて、より高速でJavaScriptによらないプログラム実行環境が模索されてきました。そこで登場したのが、WebAssemblyです。オープンソースプロダクトとしてスタートしたWebAssemblyが公開されたのは2015年です。ここから2年後となる2017年には、Mozilla Firefoxを皮切りにGoogle Chrome、Apple Safari、Microsoft Edgeの主要なブラウザでサポートされました。これによって、WebAssemblyが動作する基盤が早々に整いました。

そして2019年には、W3Cの勧告として、

が策定され、WebAssembly 1.0として正式なWeb標準に認定されました。現在も、W3CのWebAssembly Working Groupによって標準化が進められています。本稿作成時点ではWebAssembly 2.0がWorking Draftとして策定中であり、一部の機能は主要なブラウザで実装が始まっています。

なお、仕様の策定をはじめとした開発は、Google、Mozilla、Apple、Microsoftなどのブラウザベンダーによって進められています。また、Web Assemblyは、Disney+(動画配信)、Amazon Prime Video(動画配信)、Google Earth(デジタル地図)、Google Meets(ビデオ会議)、Figma(デザインツール)、Fastly(エッジコンピューティング)、Unity(ゲームエンジン)などで導入されており、動画のレンダリングやアニメーション、会議画面のぼかし処理や良好なデザイン環境の提供に効果を発揮しています。

WebAssemblyの仕組み

では、WebAssemblyとは具体的にどのような技術でしょうか?

一言でいうと、独自の命令セットを持つ仮想マシンであり、ネイティブコードに匹敵する高速なプログラムの実行をブラウザ上で可能にする仕組みです。

▲WebAssemblyの仕組み

WebAssemblyは高速・高効率で可搬性が高く安全に使える

「WebAssembly Core Specification」によると、WebAssemblyには達成すべきゴールが定められています。象徴的なものを抜粋して以下の表にまとめてみました。

▲WebAssemblyのゴール

このように、既存技術との共存を可能にしながら、性能と安全を追求した仕組みがWebAssemblyといえます。

WebAssemblyプログラムは仮想マシンで動くバイナリファイル

WebAssemblyプログラムは、拡張子が.wasmであるバイナリファイルです。ブラウザは、このバイナリファイルを読み込んでプログラムとして実行します(実行するのはJavaScript同様V8、SpiderMonkeyといった実行エンジンです)。JavaScriptプログラムが、拡張子が.jsであるファイルであり、それを読み込んで実行するのと意味合いは同じです。異なるのは、JavaScriptプログラムがテキストファイルであるのに対して、WebAssemblyプログラムがバイナリファイルであるという点です。

WebAssemblyのバイナリファイルは、専用の仮想マシンの命令(マシンコード)やデータによって構成されます。WAST(WebAssembly Abstract Syntax Tree)と呼ばれる専用のアセンブリ言語※で記述できるほか、C++やRustなどのコンパイルターゲットとして生成します。前者は難易度が高いため、後者の方法が現実的です。いずれにせよ、従来であれば、ブラウザ外でしか動かなかった言語で、ブラウザで動作するアプリを作成できる点を押さえておきましょう。
(※):アセンブリ言語とは、マシンコードとほぼ一対一でプログラムする言語。細かな記述が可能な替わりに難易度は高い。

WebAssemblyでは、仮想マシンがこのバイナリファイルをプラットフォームごとのネイティブコード(x86やARMなど)にコンパイルすることで、プログラムを高速に実行します。さらに、実行エンジンではStreaming Compilationという仕組みによってダウンロードとコンパイルを並行することで、さらなる高速化を実現しています。

WebAssemblyは万能ではない

このように、WebAssemblyプログラムは高速でさまざまな言語で作成でき、いいことづくしのように見えますが、万能ではありません。現時点では、JavaScriptを完全に置き換えられるものではなく、相互に補完しあっての利用が現実的とされています。制約として大きなところは、以下が挙げられます。

  • ・OSリソースやブラウザAPIにアクセスできない
  • ・<script>タグやimport文で直接読み込めない
  • ・扱えるデータ型が整数と浮動小数点数のみ(ともに32ビット、64ビット)

WebAssemblyは可搬性を重視しているので、特定の実行環境に依存しない設計となっています。そのため、OSリソースはもとより、ブラウザAPIも使えませんし、<script>タグで読み込んで即実行ということもできません。これは、JavaScriptプログラムの替わりに読み込んで、ウインドウを操作したり、DOMを操作したりできないという制約につながります。また、扱えるデータ型はほぼ数値型に限定されるので、オブジェクトのような複雑なデータ形式や文字列を直接には扱えません。

もし、DOMを操作したいのであれば、JavaScript側とWebAssembly側にデータ受け渡しのためのヘルパーを作成し、間接的に操作することになります。また、WebAssemblyプログラムの読み込みと実行には、WebAssembly JavaScript APIを使ったJavaScriptコードが必要です。

ちなみに、策定中のWebAssembly 2.0では、Reference TypesによってDOMの直接操作への可能性が示唆されています。並行動作時の共有制御、CPUのSIMD命令(単一命令での計算の並列実行)への対応、ガベージコレクタのJavaScriptエンジンとの共有なども実装、予定中です。WebAssemblyは登場したばかりの技術なのでまだまだ成長過程ですが、今後の進化によって使い勝手や活用分野の拡大が期待できます。

WebAssemblyプログラムの開発

WebAssemblyはさまざまなプログラミング言語で開発できますが、どのような局面で、どのような言語を使ったらいいのでしょうか。

▲WebAssemblyプログラムの開発

WebAssemblyの受け持ち範囲を適切に選択する

前述のように、WebAssemblyは既存のフロントエンド技術と共存できますが、制約もあります。当面はWebAssemblyのメリットを十分に発揮できるところで、部分的に活用していくのが現実的です。たとえば、画像処理や数値計算など、演算速度が必要な部分のみをピンポイントでWebAssemblyで実装するといった方法です。この場合は、JavaScriptコードから定義済みの関数を呼び出す感じで使うことになります。

とはいえ、Unityがブラウザゲームをターゲットにした開発を可能にしているように、ほぼすべてをWebAssembly化することも非現実的ではありません。ゲームのように、UI自体が独自のものであれば、それを含めてWebAssembly化することは可能です。ただしこの場合でも、ブラウザのCanvas APIを仲介するJavaScriptコードが必要になります。

WebAssemblyプログラムはさまざまなプログラム言語で開発できる

WebAssemblyプログラムは、50を超えるプログラミング言語で開発可能とされていますが、本稿作成時点では主に以下の表に挙げるプログラミング言語が、安定性という観点から利用可能といえるでしょう。かつては、ガベージコレクタを必要とする言語はWebAssembly化できないとされてきましたが、WasmGCというガベージコレクタがChrome、Firefoxに導入されたことで、JavaをはじめとしてKotlinやSwiftにまで選択の幅が広がっています。

▲WebAssemblyプログラムを開発できる主なプログラム言語

まず、WebAssemblyの持つ特性を最大限に生かすなら、バイナリ生成に対応した言語を使うのがよいでしょう。WebAssemblyのアセンブリ言語(WAST)、C/C++やRust、Go、Java、Kotlin、Swiftといった静的型付けのプログラミング言語が該当します。これらの言語はJavaScriptに比べると習得の難易度が高くなりますが、すでにC/C++などによる蓄積がある場合には、言語のメリットを最大限に生かせます。かつてはC/C++とRustが主に使われていましたが、GCのサポートでJavaやKotlinなどへ採用の幅が広がりました。

TypeScriptでは、AssemblyScriptというツールを使うことでWebAssemblyバイナリを生成できます。専用の型を強制されたり、イテレータ構文や例外が使えなかったりする制約はありますが、JavaScriptの延長で開発できるので、フロントエンドの経験者が取り組むには有効な選択肢です。

C#は、Webアプリの開発という制限付きですが、.NETにおけるBlazor WebAssemblyというフレームワークでWebAssemblyプログラムの開発を可能にしています。C#の学習コストはC/C++やRustほど高くはありませんが、JavaScriptやPythonと比べると若干高めになります。

PythonやRubyでは、動的型付けのインタプリタ型言語という性質上、言語のランタイムそのものをWebAssembly化するアプローチがとられてきました。CPythonやCRubyなどC言語によるリファレンス実装があるからです。このため、あくまでもWebAssemblyを試せるという段階ですが、4月に発表されたpy2wasmによりPythonプログラムのWebAssembly化が可能になり、これらの言語の活用も今後は期待されます。

なお、WebAssemblyにおける開発には、MDN(Mozilla Developer Network)の「WebAssembly | MDN」が参考になります。ここでは、C++、Rust、WASTによるチュートリアルが紹介されています。

ブラウザ外のWebAssembly実行環境

ECMAScriptにNode.jsといったブラウザ外の実行環境があるように、WebAssemblyにもブラウザ外すなわちスタンドアロンの実行環境が存在します。WebAssemblyはその経緯からブラウザでの利用が注目されがちですが、その優れた特性からブラウザ外でも活用しようという動きになっています。

WASIはOSリソース利用のためのAPI

これらの実行環境は、WASI(WebAssembly System Interface)という仕様に基づいて構築されています。WASIは、「Bytecode Alliance」という団体が主体になって策定しています。Bytecode Allianceは、Intel、Red Hat、Fastly、Mozillaなどによって2019年に発足した団体で、非ブラウザ環境(PCデスクトップ、サーバ、IoTデバイスなど)でもWebAssemblyを動作させること(outside-the-browser)を目指しています。

WASIでは、ファイルシステムやネットワーク、システムクロックといったOSリソースなどへのアクセスのためのAPIセットを定めています。これにより、ブラウザ外にWebAssemblyの活用領域が拡がる下地ができました。

WASI準拠のWebAssembly環境が増えている

本稿作成時点では、以下のリストに挙げる実行環境が存在します。

  • Wasmtime:Bytecode Alliance提供のリファレンス的存在。主にRustで実装されており、軽量、コンパクト、高速
  • Wasmer:PHPやRubyなど他言語から呼び出し可能なライブラリを構築できる
  • Lucet:Fastlyによるエッジコンピューティング用途
  • WAMR:組み込みシステム用で軽量、コンパクトに設計されている
  • WasmEdge:エッジコンピューティング用途

また、Node.jsにおいてもバージョン13.3においてWASIのサポートが始まりました。JavaScriptとNode.js、Deno、Bunのように、WebAssemblyでも多彩な実行環境の選択肢が充実しはじめています。

おわりに

今回は、第4のブラウザ言語と称され、プログラムを高速に実行できる「WebAssembly」を紹介しました。本記事をきっかけに興味を持たれたならば、ぜひWebAssemblyの技術や応用例を深めてみてください。

関連記事

人気記事

  • コピーしました

RSS
RSS