🎉

ASP.NET Core 8 RC1 Blazor 自動レンダリングモデル!

2023/09/19に公開

ASP.NET Core 8 RC1でBlazor Web Appテンプレート更新

.NET 8ではWeb UIのすべてのニーズに対してBlazorコンポーネントを使えるようにBlazorが機能強化されています。
例えば、要求に応じてサーバーからBlazorコンポーネントを静的にレンダリングしてフォーム処理できるようにしたり、Blazor ServerあるいはBlazor WebAssemblyを使用して対話的な処理を追加できるようになっています。
また、実行時にBlazor ServerとBlazor WebAssemblyのどちらを使用するかを自動的に選択することもできます。
これらの新しい機能はすべて新しいプロジェクトテンプレートによって自動的に設定されるようになってます。

上記のようにオプションが追加されました。

「対話型WebAssemblyコンポーネントを使用する」と「対話型サーバーコンポーネントを使用する」の両方が選択されている場合、テンプレートは自動レンダリングモードを使用します。

自動レンダリングモードとは

.NETランタイムとアプリがダウンロードされている間、最初はサーバーモードを使用します。ランタイムがダウンロードされると動作モードが切り替わりWebAssemblyレンダリングモードをを開始するようになります。

実際に、プロジェクトを作って動きを確認してみましょう。

プロジェクト構成

まず、サーバー側とclient側の2つのプロジェクトが作られていることが分かります。

サーバー側のprogram.csを見てみましょう

program.cs
using BlazorAppRC1.Components;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorComponents()
    .AddServerComponents()
    .AddWebAssemblyComponents();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseWebAssemblyDebugging();
}
else
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();

app.MapRazorComponents<App>()
    .AddServerRenderMode()
    .AddWebAssemblyRenderMode();

app.Run();

ホストはWebApplicationから作られています。このことから、通常のWebアプリケーションベースからhostは作られていることが分かります。これに、.NET 8ではもうおなじみの

builder.Services.AddRazorComponents()
.AddServerComponents()
.AddWebAssemblyComponents();

あたりのサービスが追加されていっています。

次に、client側のProgram.csを見てみましょう。

Program.cs
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;

var builder = WebAssemblyHostBuilder.CreateDefault(args);

await builder.Build().RunAsync();

こちらは、WebAssemblyHostBuilderベースですのでやはりBlazor WASMです。

で、PagesフォルダにはCounter.razorのみです。
Client側のPagesフォルダにあるCounter.razorに処理が書いてある感じです。

Counter.razor
@attribute [RenderModeAuto]

<PageTitle>Counter</PageTitle>

<h1>Counter</h1>

<p role="status">Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount = 0;

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

Server側のCounter.razorを見るとClient側の参照のようです。

Counter.razor
@page "/counter"

<!-- Temporary workaround until MapRazorComponents supports AddAdditionalAssemblies -->
<!-- Once that is implemented, the main project won't need to include this file -->

<BlazorAppRC1.Client.Pages.Counter />

他は、Index.razorがHome.razorに名前が変わり、FetchData.razorがWeather.razorに名前が変わった位で内容的には変化なさそうです。

では、開発者モードでネットワークの動きを見てみましょう。まずは、起動してます。
最初に読み込むのは名前が変わったHome.razorですので以前と変わらないはず。

そうおもってみたら、サーバーモードのためかWebソケットが張られているように見えます。

次に、例のCounterページを表示してみます。
これは最初サーバーモードで動作して、ロード完了とともにWebAssemblyとして動作するあれでしょうか?

見てみます。

続々と、Wasm関係のファイルが見える!
きっと、Wasmで動いてるに違いない。

試しに、カウントアップのボタンをクリックしてもネットワークは特に発生してないようなので処理はclient側で対話的処理が完成してるといえます。

Discussion