mcpField
B
blazor

blazor

github.com/managedcode開発49639 回インストール1 日前に更新
リポジトリ

blazor について

C# と Blazor でインタラクティブな Web UI を開発するためのスキルです。レンダーモード、コンポーネント設計、状態管理、プリレンダリング、性能、JavaScript 相互運用を扱い、AI バックエンドとの接続も取り上げます。

主な機能

  1. 01Static、Server、WebAssembly、Auto のレンダーモード選択
  2. 02再利用可能なコンポーネントと状態管理の設計
  3. 03プリレンダリングと状態の永続化
  4. 04JavaScript 相互運用
  5. 05リスト描画と性能の最適化

活用シーン

  1. 01C# によるインタラクティブな Web UI の構築
  2. 02SEO、リアルタイム性、オフライン要件に応じたモード選択
  3. 03プリレンダリングとハイドレーション時の重複取得の防止

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/managedcode/dotnet-skills --skill blazor

インストール後、Claude Code で/blazorを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

manifest.json
references/
anti-patterns.md
patterns.md

詳細

Blazor

起動するタイミング

  • JavaScript ではなく C# でインタラクティブな Web UI を構築するとき
  • Server、WebAssembly、Auto のレンダーモードを選択するとき
  • コンポーネント階層と状態管理を設計するとき
  • プリレンダリングとハイドレーションを処理するとき
  • 必要に応じて JavaScript と連携するとき
  • Blazor UI を AI バックエンドと接続し、.NET で AI エージェントを構築するとき

ドキュメント

参考資料

レンダーモード(.NET 8+)

モード実行場所最適な用途
Staticサーバー(インタラクティブではありません)SEO 対応ページ、マーケティングコンテンツ
InteractiveServerSignalR 経由のサーバーリアルタイムアプリ、シンクライアント
InteractiveWebAssemblyWASM 経由のブラウザーオフライン対応、クライアント中心のアプリ
InteractiveAuto最初はサーバー、その後 WASM両方の利点を活用
レンダーモードの適用
@* Per-component *@
@rendermode InteractiveServer

@* Or in App.razor for global *@
<Routes @rendermode="InteractiveAuto" />
InteractiveAuto のアーキテクチャ
First Request:
  Browser → Server (Interactive Server) → Fast response

Subsequent Requests:
  Browser → WASM (downloaded in background) → No server needed

ワークフロー

  1. 要件に基づいてレンダーモードを選択します:

    • SEO が必要ですか?Static またはプリレンダリングから始めます
    • リアルタイム性が必要ですか?InteractiveServer を使用します
    • オフライン対応が必要ですか?InteractiveWebAssembly を使用します
    • 両方が必要ですか?InteractiveAuto を使用します
  2. 再利用できるコンポーネントを設計します:

    • 小さく、役割を絞ったコンポーネント
    • カスタマイズ用のパラメーター
    • 通信用のイベント
  3. 状態を適切に処理します:

    • コンポーネントの状態はコンポーネント内に保持します
    • 共有状態にはサービス(DI)を使用します
    • [PersistentState] を使ってプリレンダリングをまたいで状態を保持します
  4. 両方の環境で検証します(Auto モードの場合)

現在のアップストリームに関する注意事項

  • dotnet/aspnetcore の v10.0.11 はサービスリリースとして扱ってください。期限切れになったクライアント永続化サーキット状態の復元に関する修正が含まれています。アップグレード時には、再接続、永続化状態の期限切れ、レンダーモード、interactive-auto のクライアント/サーバー分割の各テストを再実行してください。
  • 2026 年 8 月時点の ASP.NET Core の概要でも、Blazor はコンポーネント UI の手段として位置付けられています。サービスリリースだけでは、コンポーネントやレンダーモードのアーキテクチャ自体は変わりません。

コンポーネントパターン

基本的なコンポーネント
@* Counter.razor *@
<button @onclick="IncrementCount">
    Clicked @count times
</button>

@code {
    private int count = 0;

    [Parameter]
    public int InitialCount { get; set; } = 0;

    protected override void OnInitialized()
    {
        count = InitialCount;
    }

    private void IncrementCount() => count++;
}
パラメーターとイベントコールバック
@* Parent.razor *@
<ChildComponent Value="@value" ValueChanged="@OnValueChanged" />

@* ChildComponent.razor *@
@code {
    [Parameter] public string Value { get; set; } = "";
    [Parameter] public EventCallback<string> ValueChanged { get; set; }

    private async Task UpdateValue(string newValue)
    {
        await ValueChanged.InvokeAsync(newValue);
    }
}
状態の永続化(.NET 8+)
@* Prevents double-fetch during prerender + hydration *@
@code {
    [PersistentState]
    public List<Product> Products { get; set; } = [];

    protected override async Task OnInitializedAsync()
    {
        // Only fetches once, persisted across prerender
        Products ??= await Http.GetFromJsonAsync<List<Product>>("api/products");
    }
}

Auto モードのデータアクセスパターン

// Shared interface
public interface IProductService
{
    Task<List<Product>> GetProductsAsync();
}

// Server implementation (direct DB access)
public class ServerProductService : IProductService
{
    private readonly AppDbContext _db;
    public async Task<List<Product>> GetProductsAsync()
        => await _db.Products.ToListAsync();
}

// Client implementation (HTTP call)
public class ClientProductService : IProductService
{
    private readonly HttpClient _http;
    public async Task<List<Product>> GetProductsAsync()
        => await _http.GetFromJsonAsync<List<Product>>("api/products");
}

// Registration
// Server: builder.Services.AddScoped<IProductService, ServerProductService>();
// Client: builder.Services.AddScoped<IProductService, ClientProductService>();

避けるべきアンチパターン

アンチパターン問題点より良い方法
大規模なコンポーネント保守が難しく、レンダリングが遅くなります小さなコンポーネントに分割します
WASM からの DB への直接アクセスブラウザー内に DB はありませんHTTP API を使用します
ShouldRender を無視する不要な再レンダリングが発生します必要に応じてオーバーライドします
Server での同期 JS 相互運用SignalR サーキットをブロックしますIJSRuntime の非同期処理を使用します
エラーバウンダリがない1 つのエラーでアプリがクラッシュします<ErrorBoundary> を使用します
プリレンダリング状態を保持しないAPI 呼び出しが二重に発生します[PersistentState] を使用します

パフォーマンスのベストプラクティス

  1. 大規模なリストを仮想化します:

    <Virtualize Items="@products" Context="product">
        <ProductCard Product="@product" />
    </Virtualize>
    
  2. リストの差分検出には @key を使用します:

    @foreach (var item in items)
    {
        <ItemComponent @key="item.Id" Item="@item" />
    }
    
  3. 頻繁に発生するイベントはデバウンスします:

    private Timer? _debounceTimer;
    
    private void OnInput(ChangeEventArgs e)
    {
        _debounceTimer?.Dispose();
        _debounceTimer = new Timer(_ => InvokeAsync(DoSearch), null, 300, Timeout.Infinite);
    }
    
  4. アセンブリを遅延読み込みします(WASM):

    var assemblies = await LazyAssemblyLoader
        .LoadAssembliesAsync(["MyHeavyFeature.wasm"]);
    

JS 相互運用

C# から JavaScript を呼び出す
@inject IJSRuntime JS

await JS.InvokeVoidAsync("alert", "Hello from Blazor!");
var result = await JS.InvokeAsync<string>("prompt", "Enter name:");
JavaScript から C# を呼び出す
[JSInvokable]
public static string GetMessage() => "Hello from C#!";
DotNet.invokeMethodAsync('MyAssembly', 'GetMessage')
    .then(result => console.log(result));

提供

  • 適切なレンダーモードを設定したインタラクティブな Blazor コンポーネント
  • 効率的な状態管理とデータフロー
  • プリレンダリングのシナリオへの適切な対応
  • 仮想化によるパフォーマンスの高いリスト描画

検証

  • 選択したモードでコンポーネントが正しく描画される
  • プリレンダリングとハイドレーションの間で状態が正しく保持される
  • 不要な再描画が発生しない(ブラウザーツールで確認)
  • JS 相互運用が Server と WASM の両方で動作する
  • エラーバウンダリーがコンポーネントの障害を捕捉する
  • Auto モードが両方の環境で動作する

コメント