はじめに - "C# で SPA を作る Blazor とは?"
「C# で SPA が作れるって、どういうこと?」
「C# で SPA が作れたら何がうれしいの?」
「Blazor って、クライアントサイド版とサーバーサイド版があるって聞いたんだけど」
そんな話題については、下記スライドなどが参考になろうかと思います。
改めて - Blazor をお勧めできる人は誰か?
C# で SPA を実装できる Blazor ですが、当然のことながら、"銀の弾丸" では、まったく、ありません。
ではどういった人たちであれば、Blazor をお勧め出来るのか、考えてみました。
条件1. C# で書きたい/書くのがふさわしい人
まず、そもそも、C# でプログラムを書くことを好む人が対象となるでしょう。
すでにサーバー側 Web アプリ実装で ASP.NET を使用している人はもちろんなのですが、Xamarin や UWP、Unity、WPF に Windows Forms などなど、これまで他のプラットフォーム向けに C# で実装してきた人たちにもお勧め出来ます。
"プログラミング言語が C# だから" というだけでなく、使い慣れた IDE や既存の NuGet パッケージエコシステムなどを、Blazor アプリ開発でもそのまま活かせるのも魅力だからです。
"意地でも JavaScript を書きたくない!" という層も、消極的な理由ながら、Blazor の採用をお勧め出来る層となるかもしれません。
とはいえ、Blazor アプリを書いていても、ちょっと凝ったことをやろうとすると、JavaScript を使わないと歯が立たない場面が出てくると思います。
ですので、このような層にお勧めするのはちょっとどうかなー、という気がします。
(ちなみに、C# ではなく、Elixir な方々だと、LiveView が選択肢に挙がるようですね。)
条件2. SPA ないしは同等のユーザー体験の実現を必要としている人
条件1 に該当したとしても、そもそも SPA、すなわち Single Page Application と呼ばれるような、逐一サーバー側とのページ往復を行なうことなく、ブラウザ上でさくさくとユーザー操作とインタラクションするような、そのような Web アプリ実装を求められるかどうかで、Blazor がお勧め出来るかどうかが変わってくるかと思います。
そのようなユーザー体験が求められないような、例えば企業の紹介公式サイトのように、ほとんどユーザーとインタラクションしない場合は、たとえ C# による実装を求められたとしても、Blazor ではなく、一般的な ASP.NET サーバー側実装 (ASP.NET Core MVC とか、Razor Pages とか) で十分かとも考えられます。
なお、学習コスト的には、新たに ASP.NET Core MVC や Razor Pages を学ぶのと、Blazor を学ぶのとでは、さしたる違いはない気もします。
しかし学習コストの点では問題なくても、Blazor は一般的な他の JavaScript SPA フレームワークと比べて、トレードオフが発生します(詳しくは後述します)。
以上を勘案すると、前述のようなユーザーとの対話がほとんどないサイトの構築には、Blazor ではなく、ASP.NET Core MVC や Razor Pages などのサーバー側 Web アプリ実装のほうが好ましいのではないかと思われます。
(さらに突き詰めると静的サイトジェネレーターも選択肢に挙がると思いますが割愛)
条件3-1. 常時接続必須を許容できるか?
条件 1, 2 に該当した人は Blazor をお勧め出来る人です。
しかし次は、"サーバー側 Blazor" と "クライアント側 Blazor"、いずれのホスティングモデルを選択すべきかの判断が必要です。
ここで、サーバー側とクライアント側との常時接続が必須となることを許容できるなら、サーバー側 Blazor をお勧め出来ます。
サーバー側 Blazor は 2019年9月に公式リリースに達しており、Visual Studio や Visual Studio Code によるデバッガ支援も協力です。
また、クライアント側とサーバー側とを Web API で結ぶ必要なく、ベタにサーバー側実装を書くだけであたかも SPA のような俊敏なユーザーインタラクションを実現できるのも面白いところです。
条件3-1-1. サーバー側に .NET Core 実行環境を用意できるか?
条件3-1 に該当し、ではサーバー側 Blazor でやろうか、となった場合、文字どおり "サーバー側で動く" Blazor、すなわち本質的には ASP.NET Core なサーバー側 Web アプリ実装になるので、サーバー側に .NET Core 実行環境が必要となります。
まぁ、今日び、サーバー側として Docker コンテナが動けば .NET Core 実行環境の用意には困らないと思います (参照: ".NET Core - Docker Hub - Official images for .NET Core and ASP.NET Core")。
もちろん、PaaS として Azure Web Apps に配置するのも良いですし、「ロリポップ! マネージドクラウド」でも .NET Core が選べるようです。
とはいえサーバー側を自前でスクラッチで実装するのではなくて、Firebase で動かそうとか Netlify で動かそうとかいう場合もありましょう。
そのような場合はサーバー側実行環境として .NET Core は使えませんので、結果としてサーバー側 Blazor は選択肢から漏れることとなります。
条件3-2. サイトのコンテンツサイズが大きくなることを許容できるか?
条件 3-1 の常時接続必須が許容できない場合、例えば PWA などオフライン動作が求められる場合などは、次に選択肢にあがるのはクライアント側の Blazor です。
ただしクライアント側 Blazor は、少なくとも今のところ、そのコンテンツサイズが大きくなりがちです。
実際どれくらいのサイズになるかということで、参考例として GitHub 上で「Blazor アプリ構築ワークショップ」 (下図) が公開されているので、これを見てます。
Twitter で認証し、ピザの注文を受け付け、地図で配達状況を示す、というまずまずのボリュームの Web アプリです。
これを手元に git clone して実行してみたところ、ブラウザに読み込まれたコンテンツサイズは 6.3MB (通信は gzip 圧縮されるので、通信上の転送容量は 3.2MB) になりました。
画像類を抜くと 5.4MB (転送容量2.4MB) 程です。
ちなみにモバイル版の Twitter は、ざっくり 3MB 程でした。
このクライアント側 Blazor のコンテンツサイズの大きさが許容できない場合は、Blazor ではなく、Vue や React、Angular などの JavaScript による SPA 実装がお勧めとなります。
条件3-2-1. 処理速度を求めていないか?
ここまで、条件 1, 2, 3-1 に該当したとしても、まだ続きがあります。
今日時点のクライアント側 Blazor は、MSIL (IL、C# をコンパイルしてできあがる中間言語) をインタープリタ方式で実行しているようです。
そのため、計算機的処理速度は、JavaScript に劣ると思われます。
処理速度を求めている場合は、クライアント側 Blazor は不利と言えるでしょう。
もっとも、自分が SPA 実装を試している範囲では、体感的に重い/遅いと感じる程のことはなかったです。
なお、インタープリタ方式ではなく、ネイティブの WebAssembly コードに事前コンパイルする方式も試行が続いてはいるようです。
まとめ
以上、
- 条件1. C# で書きたい/書くのがふさわしい人
- 条件2. SPA ないしは同等のユーザー体験の実現を必要としている人
- 条件3-1. 常時接続必須を許容できるか?
- 条件3-1-1. サーバー側に .NET Core 実行環境を用意できるか?
- 条件3-2. サイトのコンテンツサイズが大きくなることを許容できるか?
- 条件3-2-1. 処理速度を求めていないか?
の条件をクリアした人が、Blazor をお勧めできる人ではないか、と考えました。
ちなみに自分は、
- サーバー側を ASP.NET Core で書いているので、クライアント/サーバー間でのモデル型の共有や、モデルへの属性ベースでの制約指定で入力検証ができることなど、利点がいっぱい (条件 1 クリア)
- ユーザーインタラクションが沢山ある業務用 Web アプリを書いている (条件 2 クリア)
- 常時接続必須であることは、要件上、許容できない (条件 3-1 NG)
- しかしサイズが大きいことはコンシューマ向けじゃないので問題にならない (多少サイズが大きくても、業務用アプリなので使わざるを得ないw) (条件 3-2 クリア)
- 業務用アプリなので、そこまで高速な処理速度は必要とされていない (条件 3-2-1 クリア)
ということで見事、クライアント側 Blazor がお勧めできる人に該当しました。
ちなみに当方、運用環境は Azure Web Apps を使ってるので、常時接続必須が許容できれば、サーバー側 Blazor も選択肢に挙がります (条件 3-1-1 クリア)
Happy Coding :)