.NET 9 Blazor:Blazor Unitedによるフルスタック開発ガイド 2026年版

.NET 9のBlazor Unitedは、静的SSR・Server・WebAssemblyの3つのレンダリングモードを統合したフルスタックフレームワークである。レンダリングモードの使い分け、ストリーミングレンダリング、コンストラクタインジェクション、本番環境向けパターンを実践的に解説する。

.NET 9 Blazor Unitedによる複数レンダリングモードのフルスタック開発

.NET 9のBlazor Unitedは、静的サーバーサイドレンダリング(SSR)、インタラクティブServer、WebAssemblyという3つのレンダリング戦略を1つのフルスタックフレームワークに統合した画期的な技術である。.NET 8で導入され、.NET 9でさらに洗練されたこの統合モデルにより、コードを書く前にBlazorのホスティングモデルを選択する必要がなくなった。

Blazor Unitedとは

Blazor Unitedを使用すると、同一アプリケーション内で静的SSR、Serverインタラクティビティ、WebAssemblyインタラクティビティを混在させることができる。各コンポーネントが独立してレンダリングモードを宣言するため、ページ単位でパフォーマンスとインタラクティビティをきめ細かく制御できる。

.NET 9 Blazor Webアプリのセットアップ

.NET 9のblazorwebテンプレートは、3つのレンダリングモードすべてに対応するプロジェクトを自動的に生成する。セットアップには.NET 9 SDK(9.0.100以降)が必要であり、1つのコマンドでサーバープロジェクトとクライアント(WASM)プロジェクトの両方が作成される。

bash
# Create a new Blazor Web App with all render modes enabled
dotnet new blazorweb -n FullStackApp --interactivity Auto --all-interactive false
cd FullStackApp
dotnet run

--interactivity Autoフラグにより、ServerとWebAssemblyの両方のレンダリングモードが有効になる。--all-interactive falseを設定すると、デフォルトのレンダリングモードが静的SSRに維持され、グローバルではなくコンポーネント単位でインタラクティビティを選択する構成になる。

.NET 9におけるBlazorレンダリングモードの理解

Blazor Webアプリのすべてのコンポーネントは、実行場所、インタラクティビティの有無、サーバーとの通信方法を決定するレンダリングモードを持つ。.NET 9では4つの異なるモードが提供されている。

| レンダリングモード | ホスティング | インタラクティビティ | 最適な用途 | |---|---|---|---| | 静的SSR | サーバー | なし | マーケティングページ、ドキュメント、SEOコンテンツ | | Interactive Server | SignalR経由サーバー | 完全 | ダッシュボード、CRUD、フォーム | | Interactive WebAssembly | WASM経由ブラウザ | 完全 | オフライン、クライアント側の重い処理 | | Interactive Auto | サーバー→WASM | 完全 | 高速ロードと独立性の両立 |

レンダリングモードは@rendermodeディレクティブ属性を使用してコンポーネントレベルで設定される。このコンポーネント単位の粒度により、1つのページ内で静的セクションとインタラクティブセクションを混在させることが可能である。

Components/Pages/Dashboard.razorcsharp
@page "/dashboard"
@rendermode InteractiveServer

<PageTitle>Dashboard</PageTitle>

<h1>Real-Time Metrics</h1>

<!-- This component renders interactively via SignalR -->
<MetricsChart />

<!-- Static content below renders as plain HTML -->
<footer>Updated every 5 seconds</footer>

.NET 9で追加されたComponentBase.RendererInfoAPIを使用すると、コンポーネントが実行時に現在のレンダリングモードを検出でき、実行コンテキストに基づいた条件分岐ロジックが実装可能になる。

Components/Shared/AdaptiveComponent.razorcsharp
@if (RendererInfo.IsInteractive)
{
    <button @onclick="HandleClick">Interactive Action</button>
}
else
{
    <a href="/fallback">Static Fallback Link</a>
}

@code {
    private void HandleClick()
    {
        // Runs only in interactive modes (Server or WASM)
    }
}

非同期処理が多いページのストリーミングレンダリング

非同期でデータを取得する静的SSRページは、すべてのタスクが完了するまでレスポンスをブロックする可能性がある。ストリーミングレンダリングは、プレースホルダーHTMLを即座に送信し、データが到着した時点で最終コンテンツをプッシュすることでこの問題を解決する。.NET 9では、[StreamRendering]属性にtrueパラメータが不要になり、デフォルトで有効になっている。

Components/Pages/Products.razorcsharp
@page "/products"
@attribute [StreamRendering]

<PageTitle>Product Catalog</PageTitle>

@if (products is null)
{
    <p>Loading products...</p>
}
else
{
    <div class="product-grid">
        @foreach (var product in products)
        {
            <ProductCard Item="@product" />
        }
    </div>
}

@code {
    private List<Product>? products;

    // Data loads asynchronously; streaming pushes updates to the browser
    protected override async Task OnInitializedAsync()
    {
        products = await ProductService.GetAllAsync();
    }
}

ストリーミングレンダリングはHTTP/1.1のチャンク転送エンコーディングに依存しており、すべてのモダンブラウザでサポートされている。プレースホルダーコンテンツが即座にレンダリングされ、完全なページリロードなしに最終マークアップに置き換えられる。

Blazorコンポーネントにおけるコンストラクタインジェクション

.NET 9では、既存の@injectディレクティブと[Inject]属性を補完する形で、Blazorコンポーネントへのコンストラクタインジェクションが導入された。C# 12のプライマリコンストラクタと組み合わせることで、サービスの依存関係がコンポーネントの型シグネチャの一部となる。

Components/Pages/OrderHistory.razorcsharp
@page "/orders"
@rendermode InteractiveServer

<h2>Order History</h2>

@if (orders is not null)
{
    <table>
        <thead>
            <tr><th>Order ID</th><th>Date</th><th>Total</th></tr>
        </thead>
        <tbody>
            @foreach (var order in orders)
            {
                <tr>
                    <td>@order.Id</td>
                    <td>@order.PlacedAt.ToShortDateString()</td>
                    <td>@order.Total.ToString("C")</td>
                </tr>
            }
        </tbody>
    </table>
}

@code {
    // Constructor injection via primary constructor
    [Inject] public required IOrderService OrderService { get; set; }
    [Inject] public required NavigationManager Nav { get; set; }

    private List<Order>? orders;

    protected override async Task OnInitializedAsync()
    {
        orders = await OrderService.GetRecentOrdersAsync();
    }
}

コンストラクタインジェクションにより依存関係が明示的になり、ユニットテストが簡素化される。Program.csで登録されたサービスは自動的に解決され、builder.Services.AddKeyedScoped<T>()で追加されたキー付きサービスも含まれる。

.NETの面接対策はできていますか?

インタラクティブなシミュレーター、flashcards、技術テストで練習しましょう。

Interactive Autoモード — 両方の利点を活かす

Autoレンダリングモードは、最も高速な体感ロード時間を実現する。初回アクセス時、コンポーネントはSignalR経由でサーバー上で実行されながら、バックグラウンドでWebAssemblyランタイムがダウンロードされる。以降のアクセスでは、実行が完全にブラウザに移行する。

Components/Pages/Chat.razorcsharp
@page "/chat"
@rendermode InteractiveAuto

<h2>Live Chat</h2>

<div class="chat-messages">
    @foreach (var msg in messages)
    {
        <div class="message">@msg.Author: @msg.Text</div>
    }
</div>

<input @bind="newMessage" @onkeydown="HandleKey" placeholder="Type a message..." />

@code {
    [Inject] public required IChatService ChatService { get; set; }

    private List<ChatMessage> messages = new();
    private string newMessage = string.Empty;

    protected override async Task OnInitializedAsync()
    {
        messages = await ChatService.GetRecentMessagesAsync();
    }

    private async Task HandleKey(KeyboardEventArgs e)
    {
        if (e.Key == "Enter" && !string.IsNullOrWhiteSpace(newMessage))
        {
            await ChatService.SendAsync(newMessage);
            newMessage = string.Empty;
        }
    }
}

Autoモードでは、コンポーネントの依存関係とロジックがサーバーとWASMの両方のコンテキストで動作する必要がある。サービスはインターフェースで抽象化し、サーバーとクライアントの両方のDIコンテナに登録する必要がある。

.NET 9における再接続とレジリエンス

.NET 9では、Blazor Serverの再接続ロジックが指数バックオフ戦略で完全に書き直された。固定間隔でリトライする代わりに、フレームワークは高速なリトライから開始し、徐々に遅延を増加させる。これにより、障害時のサーバー負荷を軽減しながら、一時的な接続断からの迅速な復旧が可能になった。

主な改善点:

  • タブに戻ると即座に再接続が試行される
  • サーバーがすでにサーキットを解放している場合、ページが自動的にリフレッシュされる
  • デフォルトUIに「サーバーに再接続中...」とプログレスインジケーターが表示される
  • リトライ間隔はBlazor.start()で設定可能
wwwroot/app.js — Custom reconnection configurationjavascript
Blazor.start({
    circuit: {
        reconnectionOptions: {
            retryIntervalMilliseconds: (retryNumber) => {
                // Exponential backoff: 200ms, 400ms, 800ms, max 30s
                return Math.min(200 * Math.pow(2, retryNumber), 30000);
            },
            maxRetries: 15
        }
    }
});

静的SSRと選択的インタラクティビティ

2026年におけるほとんどのBlazor Webアプリに推奨されるアーキテクチャは、静的SSRをデフォルトとし、必要な箇所にのみインタラクティビティを追加するというものである。[ExcludeFromInteractiveRouting]属性(.NET 9の新機能)は、静的のまま維持すべきページをマークするもので、HTTPクッキーやリクエスト/レスポンスサイクルに依存するページに有用である。

Components/Pages/Privacy.razorcsharp
@page "/privacy"
@attribute [ExcludeFromInteractiveRouting]

<PageTitle>Privacy Policy</PageTitle>

<!-- This page always renders as static HTML -->
<!-- Even if global interactivity is enabled -->
<article>
    <h1>Privacy Policy</h1>
    <p>Last updated: April 2026</p>
    <!-- Content -->
</article>

このパターンはMapStaticAssetsと相性が良い。MapStaticAssetsは.NET 9の新しいミドルウェアで、ビルド時に静的ファイルを圧縮・フィンガープリント処理し、従来のUseStaticFilesアプローチを最適化された配信に置き換える。

.NET 9 AOTコンパイルによるパフォーマンス向上

.NET 9のAOT(Ahead-of-Time)コンパイルは、.NET 8と比較してWebAssemblyペイロードサイズを最大40%削減する。Google Lighthouseベンチマークによると、Blazor WASMの起動速度は25%向上している。これらの改善は、AOTを有効にしてパブリッシュすると自動的に適用される。

bash
# Publish with AOT for production
dotnet publish -c Release -p:RunAOTCompilation=true

WebSocket圧縮もインタラクティブServerコンポーネントでデフォルトで有効になっている。圧縮関連の攻撃ベクトルを軽減するために、コンテンツセキュリティポリシー(frame-ancestors: 'self')が自動的に適用される。

今すぐ練習を始めましょう!

面接シミュレーターと技術テストで知識をテストしましょう。

まとめ

  • .NET 9のBlazor Unitedは、静的SSR、Server、WebAssemblyを単一プロジェクトに統合し、ホスティングモデルの選択を不要にする
  • @rendermodeでコンポーネントごとにレンダリングモードを設定し、SEO向けには静的、ダッシュボードにはServer、ハイブリッドシナリオにはAutoと、各ページを独立して最適化できる
  • [StreamRendering]によるストリーミングレンダリングで、非同期処理が多いページのローディング遅延を解消できる
  • .NET 9の新機能であるコンストラクタインジェクションにより、コンポーネントの依存関係が明示的かつテスト可能になる
  • Autoレンダリングモードは、Server経由の高速初期描画を提供した後、リピートアクセスでWASMに移行して完全なクライアント独立性を実現する
  • 指数バックオフによる再接続で、接続断の発生が減少し、手動ページリフレッシュが不要になる
  • AOTコンパイルにより、WASMペイロードサイズが40%削減、起動時間が25%短縮される
  • すべてのBlazor Webアプリは静的SSRをデフォルトとして開始し、UXが要求する箇所にインタラクティビティを追加するのが推奨される

今すぐ練習を始めましょう!

面接シミュレーターと技術テストで知識をテストしましょう。

タグ

#dotnet
#blazor
#aspnet-core
#webassembly
#full-stack

共有

関連記事