翻訳元: Waqas Anwar による2021年3月12日の記事 『A Beginner’s Guide To Blazor Server and WebAssembly Applications』

.NET の世界の最新動向を常に追いかけているなら、今や Blazor について聞いたことがない人はいないでしょう。現在 .NET コミュニティでは Blazor に関する大きな話題が飛び交っています。その最も一般的な理由は、大多数の .NET 開発者が何年も夢見てきたこと、すなわち「サーバー上でもブラウザ内でも C# を実行できる能力」をもたらすからです。Blazor を使えば、JavaScript ではなく HTML、CSS、C# を使って対話型 Web アプリケーションを構築できます。このチュートリアルでは、Blazor の基本概念を紹介し、Blazor で利用可能なさまざまなホスティングモデルの概要を説明します。また、各ホスティングモデルの長所と短所も紹介するので、次の Blazor プロジェクトに最適なホスティングモデルを決定するのに役立ちます。
Blazor とは?
Blazor は、無料でオープンソースのシングルページアプリケーション(SPA)開発フレームワークであり、開発者がサーバー側とクライアント側の両方で C# を使用して対話型 Web アプリケーションを構築できるようにします。Blazor は、ブラウザで C#/.NET コードを実行するために、クライアント側にプラグインをインストールする必要はありません。WebAssembly(すべての主要ブラウザでサポートされている Web 標準)を使用して .NET コードを実行します。また、Blazor はサーバー側で .NET コードを実行し UI を構築し、更新された DOM のみを SignalR 接続を介してクライアントに転送することもできます。

WebAssembly とは?
WebAssembly(Wasm と略されることもあります)は、ポータブルなバイナリ形式(低レベル命令セット)であり、これらの命令を解釈できる任意のホスト上で実行されるように設計されています。WebAssembly の主な目標は、開発者が高性能な Web アプリケーションを構築できるようにすることですが、その形式は他の環境で実行・統合できるようにも設計されています。現在、WebAssembly は Chrome、Android 版 Chrome、Edge、Firefox、Safari、Opera など、すべての主要ブラウザでサポートされています。

Blazor のホスティングモデル
Blazor のコンポーネントモデルは Blazor の核心であり、UI 変更の計算と UI のレンダリングを互いに分離するように設計されています。そのため、アプリケーションをどのようにレンダリングするかに関係なく、基本的なコンポーネントモデルは変わりません。本稿執筆時点では、4 つのレンダリング/ホスティングモデルが利用可能であり、それぞれ開発段階が異なります。
- Blazor Server
- Blazor WebAssembly
- Blazor Electron
- Mobile Blazor Bindings
Blazor Electron と Mobile Blazor Bindings は現在実験段階であり、Microsoft はこれらのホスティングモデルのリリースをまだ約束していないため、本稿では取り上げません。
Blazor Server アプリとは?
Blazor Server アプリケーションはサーバー上で動作し、完全な .NET Core ランタイムを利用できます。すべての処理はサーバー側で行われ、UI/DOM の変更は SignalR 接続を介してクライアントに返されます。この双方向の SignalR 接続は、ユーザーが初めてブラウザからアプリケーションを読み込んだときに確立されます。.NET コードは既にサーバー上で実行されているため、フロントエンド用の API を作成する必要はありません。サービスやデータベースなどに直接アクセスでき、従来のサーバーサイド技術でやりたいことは何でもできます。

§ Blazor Server を使用すべき場合
- アプリケーションを完全な .NET Core ランタイム上で実行したい場合
- アプリケーションの初期ダウンロードサイズを非常に小さく保ちたい場合
- アプリケーションの起動時間を非常に速くしたい場合
- アプリケーションのコードをサーバー上に保持し、クライアントにダウンロードさせたくない場合
- 高速なアプリケーション開発サイクルを実現し、既存の .NET 開発者にとって学習曲線がほとんど不要な場合
- アプリケーションを検索エンジンにフレンドリーにしたい場合
- WebAssembly に依存せず、古いブラウザでもアプリケーションを動作させたい場合
- Visual Studio で通常の .NET アプリケーションと同じように .NET コードをデバッグしたい場合
- イントラネットや需要の低い公開アプリケーションを構築したい場合
§ Blazor Server を使用すべきでない場合
- アプリケーションが高レイテンシ環境で動作する場合
- アプリケーションをオフラインで動作させ、サーバーとの固定 SignalR 接続を必要としない場合
- 大量の SignalR クライアント接続に対応するためにサーバーリソースを増やしたくない場合
Blazor WebAssembly アプリとは?
このホスティングモデルは、Angular、Vue、React といった最新の人気 SPA フレームワークの直接の競合であり、多くの開発者が Blazor を学びたいと思う主な理由でもあります。開発者は JavaScript の代わりに C# を使用してすべてのフロントエンド UI ロジックを記述できます。このホスティングモデルでは、最初のリクエスト時に、アプリケーションの DLL とそのすべての依存関係、および小型の Mono .NET ランタイムがクライアントにダウンロードされます。そして、クライアント上の Mono ランタイムがアプリケーションコードをロードして実行します。Blazor WebAssembly プログラムは、C、C# などの言語で記述され、WebAssembly バイトコードにコンパイルされます。

§ Blazor WebAssembly を使用すべき場合
- アプリケーション全体を静的ファイルにコンパイルし、サーバー上に .NET ランタイムを必要とせずにクライアントに提供したい場合。つまり、バックエンドは PHP、Node、Rails などで記述し、Blazor で記述されたフロントエンドアプリケーションを提供できます。
- サーバーへの継続的な接続を必要とせず、クライアント上でオフラインで動作するアプリケーションを構築したい場合。
- 処理をクライアント側に移し、サーバーの負荷を軽減したい場合。
- クライアントとサーバーの間でコードやライブラリを共有したい場合。
§ Blazor WebAssembly を使用すべきでない場合
- クライアントにダウンロードするファイル/DLL が多すぎて、ペイロードサイズを妥協できない場合。
- 起動時間(特にネットワーク接続が悪い場合)を妥協できない場合。
- ブラウザのサンドボックス環境(セキュリティ制限が完全に適用される)でアプリケーションを実行しなければならないことを妥協できない場合。
Blazor のホスティングモデルをよりよく理解するために、Visual Studio 2019 で Blazor Server アプリケーションと Blazor WebAssembly アプリケーションをそれぞれ作成してみましょう。
Visual Studio 2019 で Blazor Server アプリを作成する
Visual Studio 2019 を開き、[新しいプロジェクトの作成] をクリックします。利用可能なテンプレート一覧から Blazor App テンプレートを選択し、[次へ] をクリックします。

プロジェクト名(例:BlazorServerApp)を指定し、[次へ] をクリックします。作成する Blazor アプリケーションの種類を選択するよう求めるダイアログが表示されます。ここでは Blazor Server アプリを作成するので、Blazor Server App を選択し、[作成] ボタンをクリックします。

Visual Studio が Blazor Server アプリケーションを作成し、ソリューションエクスプローラーに以下のフォルダーとファイルが含まれます。

Blazor Server アプリで利用可能ないくつかの重要なファイルとフォルダーについて説明しましょう。
§Program.cs
このファイルには、プロジェクトのエントリポイントである Main メソッドが含まれています。Main メソッドは CreateHostBuilder メソッドを呼び出し、デフォルトの ASP.NET Core ホストを構成します。
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
§Startup.cs
これは標準の ASP.NET Core プロジェクトで使用するのと同じファイルです。重要な点は、ConfigureServices メソッド内で AddServerSideBlazor が呼び出され、Blazor Server アプリに関連するサービスが追加されることです。
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddSingleton<WeatherForecastService>();
}
このファイルの Configure メソッドには、さらに 2 行の重要なコードがあります。MapBlazorHub メソッドは Blazor Server アプリに必要な SignalR ハブエンドポイントを構成します。MapFallbackToPage メソッドは、コントローラーや Razor ページなどに一致しないすべてのリクエストを _Host ページにマッピングします。これにより、動的コンテンツのリクエストがすべて SPA フレームワークにルーティングされ、404 Not Found が返されるのを防ぎます。
app.UseEndpoints(endpoints =>
{
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
§_Host.cshtml
これはアプリケーションのルートページであり、すべての Razor コンポーネント/ページはこのホストページ内でレンダリングされます。html、head、body などの基本的な HTML 要素に加え、いくつかの特別な要素が含まれています。Blazor はコンポーネントベースのフレームワークであり、Blazor のすべてはコンポーネントであることに注意してください。<component> 要素は、アプリケーションのルートコンポーネントをレンダリングする場所を指定します。
<component type="typeof(App)" render-mode="ServerPrerendered"></component>
このファイルは末尾に blazor.server.js ファイルをインジェクトします。この JavaScript ファイルには、サーバーへの SignalR 接続を確立するコードが含まれています。この接続はブラウザがアプリケーションを読み込んだ直後に確立され、サーバーとクライアントブラウザ間のリアルタイム通信に使用されます。SignalR について詳しく知りたい場合は、私の記事「Display Live Sports Updates using ASP.NET Core SignalR」をご覧ください。
<script src="_framework/blazor.server.js"></script>
§App.razor
これは Blazor アプリの主要コンポーネントであり、ルーティングをインターセプトして Found または NotFound コンポーネントをレンダリングします。ルートに一致するコンポーネントが見つかった場合は Found コンポーネントがレンダリングされ、見つからなかった場合は NotFound コンポーネントがレンダリングされます。
<Router AppAssembly="@typeof(Program).Assembly" PreferExactMatches="@true">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
§MainLayout.cshtml
MainLayout ファイルにはアプリケーションのメインレイアウトが含まれており、そのマークアップは複数の Razor コンポーネント間で共有できます。このレイアウトコンポーネントには通常、ヘッダー、メニュー、フッター、サイドバーなどのアプリケーションの共通 UI 要素が含まれます。生成されたデフォルトの MainLayout にはサイドバーがあり、NavMenu コンポーネントをレンダリングします。また、Razor 構文 @Body を使用して、他のコンポーネントのコンテンツがレイアウトマークアップ内のどこにレンダリングされるかを指定します。
@inherits LayoutComponentBase
<div class="page">
<div class="sidebar">
<NavMenu />
</div>
<div class="main">
<div class="top-row px-4">
<a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
</div>
<div class="content px-4">@Body</div>
</div>
</div>
§wwwroot フォルダー
このフォルダーには、画像、フォント、アイコン、CSS、JavaScript ファイルなどの静的ファイルが含まれます。
§Pages フォルダーと Shared フォルダー
これらのフォルダーには、前に説明した _Host.cshtml ファイルといくつかの Razor コンポーネントが含まれています。Blazor アプリケーションは、.razor 拡張子を持つ Razor コンポーネントの集まりです。これらのコンポーネントの中には、ルートを使用してアクセスできる「ルーティング可能なコンポーネント」と呼ばれるものがあります。たとえば、アプリケーションのルート URL に移動すると、次の Index.razor コンポーネントがレンダリングされます。この URL は、Index.razor コンポーネントの上部にある @page ディレクティブで指定されます。
§Index.razor
@page "/"
<h1>Hello, world!</h1>
Welcome to your new app.
<SurveyPrompt Title="How is Blazor working for you?" />
上のページは、SurveyPrompt という子コンポーネントも使用していることに注意してください。これは @page ディレクティブがないため子コンポーネントと呼ばれ、他のコンポーネントに埋め込むことができます。
Pages フォルダーには他にもいくつかの Razor コンポーネントがあり、それぞれファイル上部で指定されたパスを使用してアクセスできます。たとえば、/counter パスに移動すると Counter コンポーネントがレンダリングされます。同様に、FetchData コンポーネントは /fetchdata パスでレンダリングされます。
Razor Server アプリケーションには、共有コンポーネントを含む Shared フォルダーもあります。これらのコンポーネントは、上で見た SurveyPrompt コンポーネントのように、アプリケーション全体の任意のコンポーネントで使用できます。Shared フォルダーにあるもう 1 つの興味深い共有コンポーネントは NavMenu コンポーネントで、Blazor Server アプリケーションのトップナビゲーションバーをレンダリングします。
§_Imports.razor
このファイルは、ASP.NET MVC Web アプリケーションの _ViewImports.cshtml ファイルに似ており、さまざまな Razor コンポーネントで使用できる名前空間のリストが含まれています。_Imports.razor ファイルでこれらすべての名前空間を宣言する利点は、各 Razor コンポーネントでそれらを繰り返しインポートする必要がないことです。
@using System.Net.Http @using Microsoft.AspNetCore.Authorization @using
Microsoft.AspNetCore.Components.Authorization @using
Microsoft.AspNetCore.Components.Forms @using
Microsoft.AspNetCore.Components.Routing @using
Microsoft.AspNetCore.Components.Web @using
Microsoft.AspNetCore.Components.Web.Virtualization @using Microsoft.JSInterop
それでは、Blazor Server アプリケーションを実行して、ブラウザで動作を確認してみましょう。Visual Studio で F5 キーを押すと、美しいデフォルトの Blazor Server アプリケーションが表示されます。サイドバーからさまざまなページに移動し、Counter ページでカウンターを使ってみてください。ページのリフレッシュやサーバーへのポストバックは発生しません。すべてがクラシックな SPA のようにスムーズかつ高速に動作し、ブラウザとサーバー間の通信はすべて SignalR 接続を介して行われています。

ブラウザの開発者ツールを開くと、すべての標準 CSS および JavaScript ファイル(blazor.server.js ファイルを含む)がクライアントにダウンロードされ、WebSocket を介した SignalR 接続が確立されていることがわかります。

Visual Studio 2019 で Blazor WebAssembly アプリを作成する
Blazor Server アプリの基本を理解し、ブラウザで動作を確認しました。次に Blazor WebAssembly アプリを作成して、両者の違いを理解しましょう。上記と同じ手順で、Visual Studio で Blazor App テンプレートを使用して新しい Blazor アプリケーションを作成します。Blazor アプリの種類を選択するよう求められたら、今度は Blazor WebAssembly App を選択します。

Visual Studio が Blazor WebAssembly アプリケーションを作成し、ソリューションエクスプローラーに以下のフォルダーとファイルが含まれます。

2 種類のアプリケーションの違いが簡単に見つかります。たとえば、Blazor WebAssembly アプリケーションには次のファイルがありません。
- _Host.cshtml
- Error.cshtml
- Startup.cs
- appsettings.json
§index.html
Blazor WebAssembly アプリケーションでは、wwwroot フォルダーに index.html ファイルがあり、これがメインページです。このファイルは末尾に blazor.webassembly.js ファイルをインジェクトします。このファイルはフレームワークによって提供され、.NET ランタイム、Blazor アプリケーション、およびそのすべての依存関係のダウンロードを処理します。また、アプリケーションを実行するためにランタイムを初期化するコードも含まれています。
§Program.cs
Blazor WebAssembly アプリケーションでは、アプリケーションのルートコンポーネントが Program.cs ファイルの Main メソッド内で指定されます。アプリケーションのルートコンポーネントは App.razor であり、これが RootComponents コレクションに追加される様子がわかります。
public class Program
{
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
await builder.Build().RunAsync();
}
}
Visual Studio で F5 キーを押すと、同様の Blazor WebAssembly アプリケーションが表示されます。サイドバーからさまざまなページに移動し、前に Blazor Server アプリで行ったように Counter ページでカウンターを使ってみてください。すべてがまったく同じように見え、サーバー側へのポストバックもありません。

すでに知っているように、Blazor WebAssembly アプリケーションはクライアントにアプリケーションとそのすべての依存関係をダウンロードします。そのため、ブラウザの開発者ツールを開くと、クライアントが大量の DLL をダウンロードしていることがわかります(最初の閲覧時のみ)。

上記のファイルはすべて最初のリクエスト時のみダウンロードされ、その後ブラウザにキャッシュされます。ページを再度リフレッシュすると、今回はダウンロードされるファイルが少ないことがわかります。

まとめ
本稿では、Blazor SPA フレームワークの基本概念を紹介し、2 つの異なるホスティングモデルでホストされる 2 つの Blazor アプリケーションを見てきました。Blazor フレームワークは Razor コンポーネントに大きく依存しているため、両方のプロジェクトのコードとファイルの大部分は同じです。これらのコンポーネントは Blazor アプリケーションの構成要素であり、使用するホスティングモデルに関係なく、同様の方法で構築できます。この記事がお役に立てましたら、ぜひ共有して知識を広めてください。
著者: Waqas Anwar
翻訳: 技術译站
リンク: 英文原文