BlazorやRustのWebAssemblyを使うべき理由

私も遅ればせながらWebAssemblyを使い出して約半年程度がたった。
元々WebAssemblyには注目していたのだが、2020年に入ってdotnetのBlazorが正式にリリースされたことをきっかけに導入を検討するケースが増えたのだ。
WebAssemblyに対する巷の情報の多くは以下のようである。

  • JSの亜種(全部JSでできるから不要)
  • ロードが遅い
  • 結局DOMの操作のうち、JSでしかできないことがたくさんある

確かにおっしゃる通りだ。これらの評価からみるとVueJSやReactからわざわざ乗り換える理由がないように思える。少なくともWebAssemblyでないとできないことは確かにない。
それでも私はフロントエンド開発にWebAssemblyを積極的に導入したいと考えている。

JavaScript(TypeScript)の特徴

JavaScriptという言語が、サーバーサイドやフロントエンドの大規模開発に向いているかと言われると向いていないと答える人も多いだろう。やはりファジーなスクリプト言語だし処理速度が気になることもある。しかしサーバーサイドの開発はJSを採用する理由はないが、フロントの開発言語はほぼJS一択だったと言っていい。つまり、WEBを開発する上でJavaScriptは避けて通れない言語なわけだ。(ブラウザを介するので)
型付けに関しては、TypeScriptなどのトランスコンパイル言語を使用して静的型付言語として扱うことも可能だが、TypeScript固有の原因でハマることもしばしばある。世の中のJavaScriptで作成されているライブラリのほとんどはTypeScriptを意識していないので、「declear Hoge」で意味をなさない型定義ファイルを作成したことがある人がほとんどではないだろうか?
JavaScriptがダメな言語だとは思わないが、サーバーサイドからフロントのイベント・データ操作、DOM操作から何から何までJSで開発というのはよろしくない気がする。

データモデル定義について

サーバーサイド言語がJSではない場合

何年も悩み続けていることがある。SPAのサイトからサーバーサイドにAPIでデータをやりとりする際にRequestやResponseのクラスを作成するのが一般的だと思う。この時サーバーサイドがC#でフロントはTypeScriptを採用しているとすると以下のようなモデルクラスを作成すると思う。

C#のリクエストクラス


    public class Request
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

TypeScriptのリクエストクラス


    export default class Request {
        public id: number
        public name: string
    }

当然言語が違うので、それぞれ同じことが書かれた2つのクラスを用意する必要がある。これは典型的でダーティな二重管理の何ものでもない。またバリデーションのルールなどは、このようなモデルクラスに記述したい場合が多いが、その場合もC#とJSのそれぞれでバリデーションの処理を行う必要があるし、モデルへのアノテーションの書き方などもそれぞれである。本当に複数人のプロジェクトにおいて、いずれのモデルの修正も漏れることなくサーバーサイド、フロントエンド両方のモデルに反映できるか?CIにてユニットテストで自動的にチェックするか?
いずれにせよ、チーム内でしっかりとしたチェック体勢と規約を定めたうえで、全てのメンバーが遵守することで正当性が担保されることは問題と言える。

サーバーサイド言語がJSの場合

サーバーサイドの言語をNodeJsで構築した場合は、全ての構造ファイルをフロントエンドと共有できるので上記の問題は解決できる。しかし当然NodeJsもTypeScriptなどのトランスコンパイル言語でやる必要がある。サーバーサイドがNodejsのexpressなどで問題ないという場合は良いかもしれないが、個人的にはexpressなどのNodejsのサーバーフレームワークは規約が弱く自由度が高すぎると思うので、複数人開発に向いているかと言われれば疑問が残る。

gRPCを使ってModelを作成

gRPCはGoogleが開発したプロトコルであり、通信プロトコルに関する技術である。このgRPCではインターフェース定義言語(.proto)で通信の際のデータ構造を定義するのだが、protoファイルから複数の言語のmodel classをコンパイルしてくれる。つまり、サーバーサイドはJavaでフロントはJavascriptであったとしても、1つのRequest(プロトコル定義)が定義されたprotoファイルからJavaのクラスとJavascriptのクラスを生成できるので、上記の2重管理問題を解決できる。
ただ、当然protoの制約がかなり多く、アプリケーションの実装上の制約が増えてしまう。またバリデーションルールをproto上に定義するのは難しく、フレームワーク(例えばspring)標準のバリデーションは使用できないと考えて良い。これは地味に痛い。
もちろんgRPCはmodelクラスを生成するために作られた技術ではなく、バックエンド間の通信などで本領を発揮するので、gRPC自体を否定しているわけではない。構造ファイルの一元管理という点においてはgRPCはそこまで良い改善策とは言えないのではという意味である。

WebAssemblyなら一つの言語で構造クラスも共有

つまり、JS以外の1つの言語でサーバーサイドもフロントエンドも開発できればModelの多重管理問題は解決できる。それにはWebAssemblyの導入が最適と思われる。今後もWebAssemblyとサーバーサイドを包括したフレームワークが次々出てきてもおかしくないので、言語も多様な選択肢がある。

JSは不要か?

WebAssemblyがJavascriptにとって変わるかと言われれば、多くの人が言っているように「断じてない」と言える。JavaSciptはDOM操作関連、アニメーション、装飾などを行うjQueryを代表とした多くのライブラリ、知見がある。また元々の役割であるHTMLの補完としては最適な言語だろう。なので今後もJSが消えて無くなることはまずないし、むしろ最もメジャーな言語であり続けるはずだ。

ところが一方で、VueJsやReact, AngularなどのJSのフレームワークではJSに役割を過度に与え過ぎていると感じているのだ。前述の通りモデル構造の問題もあるし、これらのフレームワークではデータ通信、binding、イベントフックだけでなく、サイト全体の制御までJSで行おうとしている。ここ数年これらのフレームワークを嫌と言うほど使ってきたが、複数人開発では万事OKと言うわけではなかった。(もちろんこれらはかつてないクオリティのJSフレームワークだとは思うが)

そこにWebAssemblyが広まってきて、より高いレベルのフロント開発が実現できるかもと期待しているわけだ。当然、WebAssemblyがフロントエンドで行う役割はデータ通信、binding、イベントフック、ページ制御などであり、HTMLの装飾、アニメーションなどはJSで行うべきと考えている。

WebAssemblyの欠点と課題

上記までWASMが素晴らしいという趣旨で書いてきたが、当然欠点もあるしまだまだ課題はあると思っている。もう十分初期段階を超えていると思われるので、ドキュメントや第3者の情報も多いが、それでもJS関連の情報に比べるとまだまだ少ない。

ロードが遅い

現状、Blazorでは初期のファイルの読み込みが遅い。MSが今後も最適化をしてくれることを期待しているし、ブラウザ側が改善されていくことも期待しているが、どうもこれはJSと比較して欠点と言えるだろう。明らかな欠点と認めたうえで、思うことは、今までも新しい技術は、さらに多くのインフラ負担をかけてきたということだ。15年前に現在のVueJsで構築したサイトを開こうとすると(当時のブラウザで現在のVueを実行できると仮定すると)、おそらくロードもその後の動作もかなり遅くなると思われる。つまりWASMの初回ロードが遅いという問題は現在においては欠点だが、時間が解決してくれると考える。

Blazor(MS)の問題

これはWebAssemblyというかBlazorの問題だが(そしてMacの場合の問題)、2020年9月現在デバッグが正常にできないケースがある。Windows,MacのVisual Studioでは正常にデバッグできる。しかし、Dockerコンテナ内でBlazor WebAssemblyをコンパイルしてlistenした場合の、Visual Studio Codeでのデバッグは未だできていない。もしかしたら私だけができていないのかもしれないが。
これも時間が解決しそうなものである。
「今後もMicrosoftがこのBlazorを推し続けるのか」。これが1番の問題であり心配事である。MSは今までもこのようなサービスを生み出しては破棄してきた過去があるので、今回もいきなり梯子を外される可能性はある。

まとめ

WebAssemblyにはいくつかの欠点は未だ存在する。そして完全なJSの代替となるものでもない。しかしバック-フロントエンド開発にとって大きな恩恵をもたらすものと考えている。RustやGoでも書ける。1番の問題は、普及に成功するか否かである。5年後が楽しみだ。