ASP.NET Core Razor コンポーネントのプリレンダリング
Note
これは、この記事の最新バージョンではありません。 現在のリリースについては、この記事の .NET 9 バージョンを参照してください。
重要
この情報はリリース前の製品に関する事項であり、正式版がリリースされるまでに大幅に変更される可能性があります。 Microsoft はここに示されている情報について、明示か黙示かを問わず、一切保証しません。
現在のリリースについては、この記事の .NET 9 バージョンを参照してください。
この記事では、Razor でのサーバーでレンダリングされるコンポーネントの Blazor Web App コンポーネント プリレンダリング シナリオについて説明します。
プリレンダリングは、レンダリングされたコントロールのイベント ハンドラーを有効にせずに、最初にサーバーにページ コンテンツをレンダリングするプロセスです。 サーバーは、最初の要求に応じてできるだけ早くページの HTML UI を出力します。これにより、アプリはユーザーに対してより応答性が高くなります。 プリレンダリングでは、検索エンジンによってページ ランクの計算に使用される初期 HTTP 応答のコンテンツをレンダリングすることで、検索エンジンの最適化 (SEO) を向上させることもできます。
プリレンダリングされた状態を保持する
プリレンダリングされた状態を保持しないと、プリレンダリング中に使用された状態は失われ、アプリが完全に読み込まれたときに再作成する必要があります。 いずれかの状態が非同期的に作成された場合、コンポーネントの再レンダリング時にプリレンダリングされた UI が置き換えられると、UI がちらつくことがあります。
次の PrerenderedCounter1
カウンター コンポーネントについて検討します。 コンポーネントは、OnInitialized
ライフサイクル メソッドでのプリレンダリング中に初期ランダム カウンター値を設定します。 クライアントへの SignalR 接続が確立されると、コンポーネントが再レンダリングされ、OnInitialized
の 2 回目の実行時に初期カウント値が置き換えられます。
PrerenderedCounter1.razor
:
@page "/prerendered-counter-1"
@rendermode @(new InteractiveServerRenderMode(prerender: true))
@inject ILogger<PrerenderedCounter1> Logger
<PageTitle>Prerendered Counter 1</PageTitle>
<h1>Prerendered Counter 1</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount;
protected override void OnInitialized()
{
currentCount = Random.Shared.Next(100);
Logger.LogInformation("currentCount set to {Count}", currentCount);
}
private void IncrementCount() => currentCount++;
}
アプリを実行し、コンポーネントのログを調査します。 以下に、出力の例を示します。
Note
アプリが対話型ルーティング PrerenderedCounter1
コンポーネントのページ全体の再読み込みを行う必要があります。 詳細については、「対話型ルーティングとプリレンダリングの」セクションを参照してください。
info: BlazorSample.Components.Pages.PrerenderedCounter1[0]
currentCount set to 41
info: BlazorSample.Components.Pages.PrerenderedCounter1[0]
currentCount set to 92
最初のログ カウントはプリレンダリング中に生じます。 コンポーネントが再レンダリングされると、プリレンダリング後にカウントが再び設定されます。 カウントが 41 から 92 に更新されるときにも、UI にちらつきが生じます。
プリレンダリング中にカウンターの初期値を保持するために、Blazor では、PersistentComponentState サービス (さらに、Razor Pages または MVC アプリのページまたはビューに埋め込まれたコンポーネントの場合は、コンポーネントの状態保持タグ ヘルパー) を使用してプリレンダリングされたページ内の状態の永続化をサポートしています。
プリレンダリングされた状態を保持するには、PersistentComponentState サービスを使用して、どの状態を永続化するかを決定します。 アプリが一時停止される前に、PersistentComponentState.RegisterOnPersisting によってコールバックが登録され、コンポーネントの状態が保持されます。 状態は、アプリの再開時に取得されます。
次の例は、一般的なパターンを示しています。
{TYPE}
プレースホルダーは、永続化するデータの種類を表します。{TOKEN}
プレースホルダーは、状態識別子の文字列です。nameof({VARIABLE})
の使用を検討してください。ここで、{VARIABLE}
プレースホルダーは状態を保持する変数の名前です。 状態識別子にnameof()
を使うと、引用符で囲まれた文字列の使用が回避されます。
@implements IDisposable
@inject PersistentComponentState ApplicationState
...
@code {
private {TYPE} data;
private PersistingComponentStateSubscription persistingSubscription;
protected override async Task OnInitializedAsync()
{
persistingSubscription =
ApplicationState.RegisterOnPersisting(PersistData);
if (!ApplicationState.TryTakeFromJson<{TYPE}>(
"{TOKEN}", out var restored))
{
data = await ...;
}
else
{
data = restored!;
}
}
private Task PersistData()
{
ApplicationState.PersistAsJson("{TOKEN}", data);
return Task.CompletedTask;
}
void IDisposable.Dispose()
{
persistingSubscription.Dispose();
}
}
次のカウンター コンポーネントでは、プリレンダリング中にカウンターの状態を保持し、コンポーネントを初期化するためにその状態を取得します。
PrerenderedCounter2.razor
:
@page "/prerendered-counter-2"
@implements IDisposable
@inject ILogger<PrerenderedCounter2> Logger
@inject PersistentComponentState ApplicationState
<PageTitle>Prerendered Counter 2</PageTitle>
<h1>Prerendered Counter 2</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount;
private PersistingComponentStateSubscription persistingSubscription;
protected override void OnInitialized()
{
persistingSubscription =
ApplicationState.RegisterOnPersisting(PersistCount);
if (!ApplicationState.TryTakeFromJson<int>(
nameof(currentCount), out var restoredCount))
{
currentCount = Random.Shared.Next(100);
Logger.LogInformation("currentCount set to {Count}", currentCount);
}
else
{
currentCount = restoredCount!;
Logger.LogInformation("currentCount restored to {Count}", currentCount);
}
}
private Task PersistCount()
{
ApplicationState.PersistAsJson(nameof(currentCount), currentCount);
return Task.CompletedTask;
}
void IDisposable.Dispose() => persistingSubscription.Dispose();
private void IncrementCount() => currentCount++;
}
コンポーネントが実行されると、プリレンダリング中に currentCount
が 1 回だけ設定されます。 この値は、コンポーネントが再レンダリングされると復元されます。 以下に、出力の例を示します。
Note
アプリが対話型ルーティング PrerenderedCounter2
コンポーネントのページ全体の再読み込みを行う必要があります。 詳細については、「対話型ルーティングとプリレンダリングの」セクションを参照してください。
info: BlazorSample.Components.Pages.PrerenderedCounter2[0]
currentCount set to 96
info: BlazorSample.Components.Pages.PrerenderedCounter2[0]
currentCount restored to 96
プリレンダリング中に使用されたのと同じ状態でコンポーネントを初期化することにより、負荷の高い初期化ステップが 1 回だけ実行されます。 レンダリングされた UI もプリレンダリングされた UI に一致するので、ブラウザーでちらつきは発生しません。
永続化されたプリレンダリングされた状態はクライアントに転送され、そこでコンポーネントの状態を復元するために使用されます。 クライアント側のレンダリング (CSR、 InteractiveWebAssembly
) 中に、データはブラウザーに公開され、機密情報を含めてはなりません。 対話型のサーバー側レンダリング (対話型 SSR、 InteractiveServer
) 中に、コア データ保護 ASP.NET データが安全に転送されるようにします。 InteractiveAuto
レンダリング モードは WebAssembly とサーバーの対話機能を組み合わせたものなので、CSR の場合と同様に、ブラウザーへのデータ公開を考慮する必要があります。
ページとビューに埋め込まれたコンポーネント (Razor Pages/MVC)
Razor Pages または MVC アプリのページまたはビューに埋め込まれたコンポーネントの場合は、アプリのレイアウトの終了 タグ内に <persist-component-state />
HTML タグを含む</body>
を追加する必要があります。 これは、Razor Pages アプリと MVC アプリでのみ必要です。 詳細については、「ASP.NET Core でのコンポーネントの状態保持タグ ヘルパー」を参照してください。
Pages/Shared/_Layout.cshtml
:
<body>
...
<persist-component-state />
</body>
対話型ルーティングとプリレンダリング
Routes
コンポーネントでレンダリング モードが定義されていない場合、アプリはページ単位/コンポーネントごとの対話機能とナビゲーションを使用します。 ページ単位またはコンポーネント単位のナビゲーションを使用すると、内部†ナビゲーションは、アプリが対話型になった後 拡張ルーティング によって処理されます。 †この文脈での内部 とは、ナビゲーション イベントの URL の宛先がアプリ内の Blazor エンドポイントであることを意味します。
PersistentComponentState サービスは、初期ページ読み込みでのみ機能し、内部拡張ページ ナビゲーション イベントでは機能しません。
永続的なコンポーネントの状態を利用するページへの完全な (拡張されていない) ナビゲーションをアプリが実行すると、永続化された状態が対話型になったときにアプリで使用できるようになります。
対話型回線が既に確立されていて、永続的なコンポーネントの状態を利用するページへの拡張ナビゲーションが実行されている場合、コンポーネントがを使用するために、既存の回線では状態
このシナリオに対処するための Blazor フレームワークの追加作業は、.NET 10 (2025 年 11 月) で検討されています。 でサポートされていない回避策の詳細とコミュニティの説明については、「拡張ページナビゲーション (dotnet/aspnetcore
#51584)での永続的なコンポーネントの状態のサポート」を参照してください。 ‡サポートされていない回避策は、Blazor アプリで使用するために Microsoft によって承認されていません。 サードパーティ製のパッケージ、アプローチ、コードは、ご自身の責任で使用してください。
パフォーマンスを低下させる一方で、内部ページ要求の
プリレンダリング ガイダンス
プリレンダリング ガイダンスは、Blazor ドキュメント内で主題別に整理されています。 次のリンクは、主題別に設定された、ドキュメント全体のすべてのプリレンダリング ガイダンスを含んでいます。
基礎
コンポーネント
- プリレンダリング中に
<head>
の内容を制御する - プリレンダリングに関連する Razor コンポーネント ライフサイクルの話題
- コンポーネントの初期化 (
OnInitialized{Async}
) - コンポーネントのレンダリング後 (
OnAfterRender{Async}
) - プリレンダリング後のステートフル再接続
- JavaScript 相互運用を使用したプリレンダリング: このセクションは、.NET からの JavaScript の呼び出しおよび JavaScript からの .NET の呼び出しに関する 2 つの JS 相互運用に関する記事にも記載されています。
- レンダーで不完全な非同期アクションを処理する: サーバーでのプリレンダリング中に実行時間の長いライフサイクル タスクが原因でレンダリングが遅延する場合のガイダンス。
- コンポーネントの初期化 (
- QuickGrid コンポーネント サンプル アプリ: QuickGrid for Blazor サンプル アプリは GitHub Pages でホストされています。 コミュニティによって管理される
BlazorWasmPrerendering.Build
GitHub プロジェクトを使用した静的プリレンダリングにより、このサイトは高速に読み込まれます。 - コンポーネントを Razor Pages アプリおよび MVC アプリに統合するときのプリレンダリング
- プリレンダリング中に
認証と権限承認
状態管理: プリレンダリングを処理する: "プリレンダリングの処理" に関するセクションに加えて、この記事の他のいくつかのセクションにプリレンダリングに関する解説が含まれています。
ASP.NET Core