.NET 8 以降の Blazor Web App では、コンポーネントレベルでレンダーモードを選択できるようになりました。従来のホスティングモデルという概念から、レンダーモードという概念に変わり、より柔軟にアプリケーションを構築できます。
特徴:
- サーバーで HTML を生成し、インタラクティブ機能なし
- 最も高速な初期読み込み
- SEO に最適
- イベントハンドラーは動作しない
使うべき場面:
- 静的なコンテンツ表示
- SEO が重要なページ
- 高速な初期読み込みが必要
- データ表示のみのページ
特徴:
- SignalR を使用したサーバーサイドでのインタラクティブ処理
- 完全な .NET API アクセス
- サーバーリソースを活用
- リアルタイム通信
使うべき場面:
- サーバーリソースへの直接アクセスが必要
- 完全な .NET API が必要
- セキュリティが重要(コードがサーバー側に保護される)
- データベースアクセスが頻繁
- リアルタイム機能が必要
特徴:
- クライアントサイドで実行
- オフライン動作可能
- サーバー負荷軽減
- 静的ホスティング可能
使うべき場面:
- オフライン動作が必要
- サーバー負荷を軽減したい
- 静的サイトホスティング(CDN)を使用
- クライアント側で重い処理を実行
- PWA (Progressive Web App) を構築
特徴:
- 初回はサーバーサイドで実行
- バックグラウンドで WebAssembly をダウンロード
- 2回目以降の訪問時は WebAssembly で実行
- 両方の利点を組み合わせ
使うべき場面:
- 初回の高速読み込みとその後の高性能を両立したい
- ユーザーが繰り返し訪問するアプリケーション
- 最適なユーザーエクスペリエンスを提供したい
- 開発コスト: Server と WebAssembly の両方に対応する必要があり、実装難易度が大幅に上がる
- 運用コスト: サーバーリソースとクライアントリソースの両方を管理する必要がある
- デバッグ: 2つの異なる実行環境でのテストと問題の切り分けが必要
- バンドルサイズ: WebAssembly のダウンロードが必要で、初期表示は早いが総データ量は多い
特徴:
- 完全にクライアントサイドで実行される単独アプリケーション
- ASP.NET Core サーバーが不要
- 静的ファイルとして配信可能
- CDN やスタティックホスティングサービスで配信可能
使うべき場面:
- サーバーを持たないアプリケーション
- 完全にオフラインで動作するアプリケーション
- GitHub Pages や Azure Static Web Apps での配信
- シンプルな SPA (Single Page Application) を構築
- サーバーコストを削減したい
制限事項:
- .NET API のサブセットのみ利用可能
- 初期読み込み時間が長い
- サーバー側機能は Web API 経由でのみアクセス可能
以下のフローチャートは、Blazor アプリケーションの選択を3段階に分けて示しています。まずアプリケーションの基本的な構成を決定し、次にインタラクティブ性の適用範囲を選択し、最後に具体的なレンダーモードを決定します。
💡 インタラクティブ機能とは?
- あり: ボタンクリック、フォーム入力、リアルタイム更新など、ユーザーの操作に応じて画面が動的に変化する機能
- なし: 静的なHTMLページと同様で、リンクやフォーム送信による画面遷移のみ可能
%%{init: {'theme':'dark', 'themeVariables': { 'primaryColor': '#2c3e50', 'primaryTextColor': '#ecf0f1', 'primaryBorderColor': '#3498db', 'lineColor': '#ecf0f1', 'secondaryColor': '#34495e', 'tertiaryColor': '#4a4a4a'}}}%%
flowchart TD
Start([アプリケーションを作成したい]) --> Server{サーバーが必要?}
Server -->|サーバーが不要| Hosting{ホスティング方法は?}
Server -->|サーバーが必要| BlazorWebApp[Blazor Web App]
Hosting -->|静的サイトホスティング<br/>CDN配信| Static{オフライン動作が必要?}
Hosting -->|サーバーありホスティング| BlazorWebApp
Static -->|オフライン動作が必要| Standalone[Blazor WebAssembly<br/>Standalone]
Static -->|オフライン動作が不要| BlazorWebApp
%% 補足情報
Standalone -.-> StandaloneFeatures[✓ 静的ファイル配信<br/>✓ CDN対応<br/>✓ オフライン動作<br/>✓ PWA対応<br/>✗ 初期読み込み時間が長い<br/>✗ .NET API制限あり]
BlazorWebApp -.-> WebAppFeatures[✓ サーバーリソース活用<br/>✓ 完全な.NET API<br/>✓ 高速な初期読み込み<br/>✓ 柔軟なレンダーモード<br/>✗ サーバー必要<br/>✗ 常時接続必要]
%% スタイリング
classDef decision fill:#2c3e50,stroke:#3498db,stroke-width:2px,color:#3498db
classDef endpoint fill:#2c4a2c,stroke:#27ae60,stroke-width:2px,color:#27ae60
classDef info fill:#4a4a4a,stroke:#f39c12,stroke-width:2px,color:#f39c12
classDef start fill:#34495e,stroke:#ecf0f1,stroke-width:2px,color:#ecf0f1
class Server,Hosting,Static decision
class Standalone,BlazorWebApp endpoint
class StandaloneFeatures,WebAppFeatures info
class Start start
%%{init: {'theme':'dark', 'themeVariables': { 'primaryColor': '#2c3e50', 'primaryTextColor': '#ecf0f1', 'primaryBorderColor': '#3498db', 'lineColor': '#ecf0f1', 'secondaryColor': '#34495e', 'tertiaryColor': '#4a4a4a'}}}%%
flowchart TD
Start([Blazor Web App を選択]) --> Interactive{インタラクティブ機能が必要?}
Interactive -->|インタラクティブ機能が不要<br/>📝 静的コンテンツのみ| StaticSSR[Static SSR のみ]
Interactive -->|インタラクティブ機能が必要<br/>📝 動的な画面更新が必要| AppType{アプリケーションの特性は?}
AppType -->|単一機能<br/>一貫性重視| Global[グローバル<br/>インタラクティブ性]
AppType -->|複数機能<br/>最適化重視| PerPage[ページ単位<br/>インタラクティブ性]
%% 補足情報
StaticSSR -.-> StaticFeatures[✓ 最高速度<br/>✓ SEO最適<br/>✓ 管理が簡単<br/>✗ イベント処理不可]
Global -.-> GlobalFeatures[✓ 管理が簡単<br/>✓ 一貫性のあるUX<br/>✓ 単一機能アプリに最適<br/>✗ 柔軟性に欠ける]
PerPage -.-> PerPageFeatures[✓ ページごとに最適化<br/>✓ 柔軟性が高い<br/>✓ 静的ページと混在可能<br/>✗ 管理が複雑<br/>✗ 実装コストが高い]
%% スタイリング
classDef decision fill:#2c3e50,stroke:#3498db,stroke-width:2px,color:#3498db
classDef endpoint fill:#2c4a2c,stroke:#27ae60,stroke-width:2px,color:#27ae60
classDef info fill:#4a4a4a,stroke:#f39c12,stroke-width:2px,color:#f39c12
classDef start fill:#34495e,stroke:#ecf0f1,stroke-width:2px,color:#ecf0f1
class Interactive,AppType decision
class StaticSSR,Global,PerPage endpoint
class StaticFeatures,GlobalFeatures,PerPageFeatures info
class Start start
%%{init: {'theme':'dark', 'themeVariables': { 'primaryColor': '#2c3e50', 'primaryTextColor': '#ecf0f1', 'primaryBorderColor': '#3498db', 'lineColor': '#ecf0f1', 'secondaryColor': '#34495e', 'tertiaryColor': '#4a4a4a'}}}%%
flowchart TD
Start([インタラクティブレンダーモードを選択]) --> Priority{優先する要素は?}
Priority -->|サーバーリソース重視<br/>セキュリティ重視| Server[Interactive Server]
Priority -->|オフライン対応<br/>クライアント処理重視| WASM[Interactive WebAssembly]
Priority -->|最適なUX<br/>初回速度+継続性能| AutoCheck{実装・運用コストを<br/>許容できる?}
AutoCheck -->|はい<br/>十分なリソースあり| Auto[Interactive Auto]
AutoCheck -->|いいえ<br/>リソース不足| Fallback{代替案を検討}
Fallback -->|サーバー重視| Server
Fallback -->|クライアント重視| WASM
%% 警告
Auto -.->|⚠️ 注意| AutoWarning[実装コストが2倍<br/>Server+WASM両対応必要<br/>デバッグが複雑<br/>運用コストが高い]
%% 補足情報
Server -.-> ServerFeatures[✓ 完全な.NET API<br/>✓ サーバーリソース活用<br/>✓ セキュリティ<br/>✓ 実装が簡単<br/>✗ 常時接続必要]
WASM -.-> WASMFeatures[✓ オフライン動作<br/>✓ クライアント処理<br/>✓ サーバー負荷軽減<br/>✗ 初期読み込み時間<br/>✗ .NET API制限]
%% スタイリング
classDef decision fill:#2c3e50,stroke:#3498db,stroke-width:2px,color:#3498db
classDef endpoint fill:#2c4a2c,stroke:#27ae60,stroke-width:2px,color:#27ae60
classDef autoMode fill:#4a2c2c,stroke:#ff6b6b,stroke-width:2px,color:#ff6b6b
classDef warning fill:#4a4a4a,stroke:#ffd700,stroke-width:2px,color:#ffd700
classDef info fill:#4a4a4a,stroke:#f39c12,stroke-width:2px,color:#f39c12
classDef start fill:#34495e,stroke:#ecf0f1,stroke-width:2px,color:#ecf0f1
class Priority,AutoCheck,Fallback decision
class Server,WASM endpoint
class Auto autoMode
class AutoWarning warning
class ServerFeatures,WASMFeatures info
class Start start
- アプリケーション全体で同じレンダーモードを使用
- 管理が簡単で、一貫性のあるユーザーエクスペリエンス
- 単一機能のアプリケーションに適している
- ページやコンポーネントごとに異なるレンダーモードを選択可能
- 各ページの要件に応じた最適化が可能
- より複雑だが、柔軟性が高い
| 要件 | 推奨選択肢 | 実装難易度 |
|---|---|---|
| 高速な初期読み込み | Static SSR | 低 |
| SEO 最適化 | Static SSR | 低 |
| オフライン動作 | Interactive WebAssembly / Blazor WebAssembly Standalone | 中 |
| 完全な .NET API アクセス | Interactive Server | 低 |
| リアルタイム通信 | Interactive Server | 中 |
| サーバー負荷軽減 | Interactive WebAssembly / Blazor WebAssembly Standalone | 中 |
| 静的ホスティング | Interactive WebAssembly / Blazor WebAssembly Standalone | 中 |
| 最適なUX(初回+継続) | Interactive Auto | 高 |
| セキュリティ重視 | Interactive Server | 低 |
| サーバーレス | Blazor WebAssembly Standalone | 中 |
- 選択肢: Blazor Web App(混在モード)
- 静的ページ(会社情報、製品紹介など): Static SSR(SEO重視)
- お問い合わせフォーム: Interactive Server(データベースアクセス)
- 選択肢: Blazor Web App(混在モード)
- 商品一覧ページ: Static SSR(SEO重視)
- ショッピングカート: Interactive WebAssembly(オフライン対応)
- 選択肢: Blazor Web App(Interactive Server グローバル)
- 推奨理由: 業務アプリケーションは通常、データベースアクセスが頻繁でセキュリティが重要。Interactive Auto は開発・運用コストが高いため、特別な要件がない限り Interactive Server を推奨
- 備考: 繰り返し利用される業務アプリで、かつ開発・運用リソースが十分にある場合のみ Interactive Auto を検討
- 選択肢: Blazor WebAssembly Standalone
- GitHub Pages で配信: 静的ホスティング
- 完全にオフライン動作: サーバー不要
- 選択肢: Blazor WebAssembly Standalone
- CDN で配信: コスト削減
- シンプルな SPA: サーバーレス
- エンタープライズアプリケーションで、開発・運用チームが充実している
- 頻繁に利用されるアプリケーションで、UX への投資対効果が高い
- 長期運用が前提で、初期投資コストを回収できる見込みがある
- 技術的負債を管理できる体制が整っている
- 親コンポーネントのレンダーモードが子コンポーネントに伝播される
- 異なるインタラクティブモード間での切り替えは不可
- Static 親から Interactive 子にパラメータを渡す場合、JSON シリアライズ可能である必要がある
- RenderFragment や子コンテンツは渡せない
- WebAssembly や Auto モードを使用する場合、
.Clientプロジェクトが必要 - WebAssembly コンポーネントは
.Clientプロジェクトに配置 - Blazor WebAssembly Standalone は単一プロジェクト構成
- Interactive Auto の場合: Server と Client の両方のプロジェクトを管理する必要があり、依存関係の管理が複雑化
- 開発時間: 単一モードの約2倍の実装時間が必要
- テスト工数: Server と WebAssembly の両方での動作確認が必要
- 保守性: 2つの実行環境での問題の切り分けと対応が必要
- チーム要件: Server 側と Client 側の両方の技術スタックに精通したメンバーが必要
Interactive Server、Interactive WebAssembly、Interactive Auto の3つのモードは、デフォルトでプリレンダリングが有効になっています。
プリレンダリングとは:
- サーバー側で最初にHTMLを生成し、クライアント側で再度レンダリングを行う仕組み
- SEO最適化には有効だが、意識をしていないと処理が2重実行される場合がある
プリレンダリングが不要なケース:
- 業務アプリケーションなど、SEOが不要なアプリケーション
- 初期化処理が重い場合(データベースアクセス、Web API呼び出しなど)
- クライアント専用のサービス(WebAssembly専用API)を使用する場合
プリレンダリングの無効化方法:
<!-- Interactive Server -->
<MyComponent @rendermode="new InteractiveServerRenderMode(prerender: false)" />
<!-- Interactive WebAssembly -->
<MyComponent @rendermode="new InteractiveWebAssemblyRenderMode(prerender: false)" />
<!-- Interactive Auto -->
<MyComponent @rendermode="new InteractiveAutoRenderMode(prerender: false)" />@rendermode @(new InteractiveServerRenderMode(prerender: false))Components/App.razor で設定:
<Routes @rendermode="new InteractiveServerRenderMode(prerender: false)" />
<HeadOutlet @rendermode="new InteractiveServerRenderMode(prerender: false)" />頻繁に使用する場合は、カスタムクラスを作成して省略記法を定義:
1. カスタムクラスを作成(例:CustomRenderModes.cs):
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
public static class CustomRenderModes
{
public static IComponentRenderMode InteractiveServerWithoutPrerendering { get; } =
new InteractiveServerRenderMode(prerender: false);
public static IComponentRenderMode InteractiveWebAssemblyWithoutPrerendering { get; } =
new InteractiveWebAssemblyRenderMode(prerender: false);
public static IComponentRenderMode InteractiveAutoWithoutPrerendering { get; } =
new InteractiveAutoRenderMode(prerender: false);
}2. Components/_Imports.razor で using を追加:
@using static CustomRenderModes3. 使用例:
@rendermode InteractiveServerWithoutPrerendering- プリレンダリングを無効化すると、SEO効果が低下する
- 初期表示が遅くなる可能性がある
- 業務アプリケーションではSEOが不要な場合が多いため、パフォーマンスを優先してプリレンダリングを無効化することを推奨