Blazorで踏み込むWebAssemblyの世界


この記事は弥生 Advent Calendar 2020の6日目の記事です。

#前書き
寄稿させて頂くに辺り何を書こうかそれなりに(40秒くらい)悩んだのですが、
私はWindows3.0からの敬虔なMicrosoft教徒であるからに、
浮かぶ話題も基本MS関連となりまして。具体的には以下。

・.Net5とC#9.0
・ものすごい雑なMicrosoftの歴史
・WebAssemblyとBlazor
・こっそり仕込める一行で壊すC#アプリケーション

本命は一番上の.Net5とC#9.0だったのですが、同アドベントカレンダーの3日に纏めて下さってるので却下、
2番目は時間的に無理、4番目は.Net5(もっと前かも)だと修正されてたのでこれまた没。

というわけで消去法で何番煎じかわかりませんが、
3つ目を改題して「Blazorで踏み込むWebAssemblyの世界」をお題とさせていただきます。
対象は「C#チョットワカリマス」くらいの人ならわかるよう書いているつもり。
なお現時点は12/5の11:33。間に合うのか。

#そもそもWebAssemblyとはなんぞや？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/25645759-6667-d9ce-9a18-52dbb485d6fb.png)

WebAssembly(以下WASM)とはアセンブリをブラウザ上で実行できるようにする技術、
また[その技術を推進する団体](https://webassembly.org/)のことです。
「効率的かつ迅速な処理」「VMを介した高度なセキュリティ」「デバッグの容易性」
「主要なブラウザ上での動作保証」「下位互換の維持」など、
既存のWebサイト開発の問題点に対する回答をこれでもかと詰め込んでいるプロジェクトです。

ざっくりいうと各種処理の高速化または、JavaScriptではできないことを実現するための技術と
考えてもらえればだいたい（てきとう）あってるのではないかと。
個人的にはBlazorの発表当時に知った技術ですが、知った瞬間からわーきゃー言って絶賛追っかけ中。

#Blazorって？
[公式ドキュメント(ASP.NET Core Blazor の概要 | Microsoft Docs)](https://docs.microsoft.com/ja-jp/aspnet/core/blazor/?view=aspnetcore-5.0&WT.mc_id=AI-MVP-5002987)

ASP.NET3.0からWebサイトを作成する(たぶん)主役であった、
R@zorの後継ポジションに当たるフレームワークです。
大別して「Blazor Server Application」と「Blazor WebAssembly」の二つに分けられます。
SPAクライアントもブラウザ上で実行するコードも.NETで書けるという素敵なフレームワーク。

……余談ですが、@が炎に包まれたようなアイコンをしています。
「r@zorの進化」を表現している素敵アイコンなので
ぺたりと画像貼ってくれようと思ったんですが、__公式で配布されていない模様__なので各自で検索してください。

#Blazor二種の違いは？
サイトアクセス時にダウンロードされるファイルの内容が異なります。
具体的には、従来であればサーバー側での処理を実行するモジュールを
ローカルにダウンロードするWASMのほうが圧倒的に量が多くなっています。
当然ながらこれは初回起動時にはデータ転送量が増えるというデメリットとなります。
とはいっても、ダウンロードが完了してしまえば通信を介さず各種処理を行えるため、
ボトルネックを一つ無視することができます（キャッシュも当然有効）。
具体的にはフロントとサーバーでやっていたバリデーションが1回で済むとか。

#利点は？
既存のライブラリを利用できること、統一言語による開発、プラットフォームへの不依存など
元から生産性の高いC#という言語の恩恵を最大限受けられます。

#というわけで試してみる
Visual Studio2019をインストール、更新すればテンプレートに出てきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/5290a905-51d8-b9fe-ba61-160fcceecc6f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/fbb97018-668d-db96-b88d-070c8988e648.png)

プロジェクト名は適当に。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/6a21f0b7-3adb-5563-c872-5caa45e166b0.png)

ここで「Server Application」と「WASM」の選択があります。作成を押下すると…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/515da87e-75a9-4672-4f9c-2b0e6be636d9.png)

しばらく待った後、この画面になります。この状態でF5(デバッグ起動)を押すと…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/e5497499-2b3b-adb7-5b8e-d11e0de4fbde.png)

なんか出てきます。もうこれだけでSPAができちゃってるという。すごい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/84ae144f-87ae-4b73-440c-be3a61958b43.png)

#動かしてみる
左メニューには"Counter"と"Fetch data"というリンクがあります。
これはそれぞれSPAの機能サンプルとして用意されたものです。
"Counter"ページを開くと、カウンタとボタンだけが設置されたページが表示され、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/6d453ad5-9a46-f2a1-878f-c34b12893455.png)

ボタンを押すとカウンタが増えていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/4a1be52a-34dc-6915-6bc3-e4e40facb5a5.png)

"Fetch Data"ページを開くとどこかの天気情報が出てきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/0b4175d5-4e6a-0b65-f101-46d32b8bdb9f.png)

#ソースを見てみる1(Counter.razor)
"Counter"ページのソースはPages/Counter.razorに存在します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/c10895ab-6e85-9bec-e649-45681341b794.png)

わずか17行。で、クライアントサイドのhtml要素とC#でのカウンタが実装されていることがわかります。
特筆すべきは7行目と9-16行目。

```Counter.razor
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
    }
}
```

@onClickという記載方法でC#のメソッドを直接呼び出しているのがわかります。

#実際にどのように展開されているか見てみる
展開されたhtmlソースをのぞいてみます。なにやら怪しげな記述がありますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/7a057e91-8d2b-0916-5455-4412f963a59f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/cd0edcf5-a0ed-c151-efb4-3516c20dfdcb.png)

メソッド＿wasmmodulecallback＿()は"_framework/blazor.webassembly.js"に内包されているJavaScriptのようです。
これの実体を追ってみると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/f971cdd2-f61a-fc19-6484-cf5f54f4f082.png)

見なかったことにします。
　
　
　
　
　
　
　







![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/4d7b7a5e-630e-e99a-95f7-a7f6b3bc8d5b.png)


……冗談はともかく(半分本気)、中で何をしているかざっくり追うとWabAssemblyのモジュールをストリームで読み込んでいるようです。
この辺のMicrosoft提供ソースが難しいこと全部吸収してくれているわけですね。

推測ですが、Dll化されたモジュール内にC#コードのロジックが格納され、
jsからのキックでバイナリが実行される仕組みが確立しているのでしょう。
つまり上記記法でC#メソッドが呼び放題なわけです。ボーテ！100点！

#ソースを見てみる2(FetchData.razor)
"Fetch Data"ページのソースはPages/FetchData.razorに存在します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/e90a8122-5a91-1ef5-a1d3-2d29a08aadae.png)
計56行。てっきり通信して謎の現地の気象情報をリアルタイムでとってきてるかと思ったら、
weather.jsonを読み込んで表示しているだけで、面白いことは特になかったので割愛します。
__手抜きではない__です。

#終わりに
というわけでざっくり試してみた結果、
プログラムの基本さえ分かっていればさっくりWebサイトを作れそうなことがわかりました。

また、ローカルリソースでの処理という観点で見た場合、
最大のリスクとなりうるサーバー内処理の一部をクライアントに譲渡することで
負荷軽減となるのも大きなメリットだと思います。

学習という面でも、少し前のトレンドの「TypeScript + Webサーバーを何かしらの言語」での
Web開発は、学習コストが高くつき(=ハードルが高く、当然挫折の可能性も……)ましたが、
Blazorはそのシンプルさ故に初心者の導入としてもよい選択となるのではないでしょうか。
いろいろと可能性の塊であると感じます（※個人の感想です。効果には個人差があります）。

この記事でWebAssembly及び、Blazorにご興味お持ちいただけたら幸いです。
お読みいただきありがとうございました。