mcpField
D
dotnet-aot-wasm

dotnet-aot-wasm

github.com/wshaddix開発8671 回インストール35 週間前に更新
リポジトリ

dotnet-aot-wasm について

Blazor WASM と Uno WASM アプリの AOT コンパイルを解説するスキルです。ダウンロードサイズと実行速度の兼ね合いを示し、トリミング、遅延読み込み、Brotli 圧縮を扱います。

主な機能

  1. 01WASM のダウンロードサイズと実行速度の比較
  2. 02Blazor と Uno WASM の AOT 設定
  3. 03AOT とトリミングの併用
  4. 04遅延読み込みによるアセンブリ取得の延期
  5. 05Brotli 事前圧縮による転送の最適化

活用シーン

  1. 01CPU 負荷の高い WASM 処理の高速化
  2. 02初期ダウンロードと実行性能の調整
  3. 03必要時までオプションモジュールを読み込まない構成

インストール

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

$npx skills add https://github.com/wshaddix/dotnet-skills --skill dotnet-aot-wasm

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

詳細

dotnet-aot-wasm

Blazor WASM および Uno WASM アプリケーション向けの WebAssembly AOT コンパイル:コンパイルパイプライン、ダウンロードサイズと実行速度のトレードオフ、トリミングとの相互作用、アセンブリの遅延読み込み、ダウンロードを最適化するための Brotli による事前圧縮について説明します。

バージョンに関する前提: .NET 8.0 以降を基準とします。Blazor WASM の AOT は .NET 6 で導入され、.NET 8~10 で改良されてきました。Uno WASM も Uno 固有のツールを使用した同様のコンパイルパイプラインを採用しています。

重要なトレードオフ: トリミングと AOT は、WASM 成果物のサイズに逆の影響を与えます。トリミングは未使用コードを削除してダウンロードサイズを小さくします。AOT は成果物のサイズを増やします(ネイティブ WASM コードは IL より大きいものの、実行速度は向上します)。最適なバランスを得るには、両方を組み合わせて使用してください。

対象外: サーバーサイド .NET 向けの Native AOT については、[skill:dotnet-native-aot] を参照してください。AOT を前提とした設計パターンについては、[skill:dotnet-aot-architecture] を参照してください。トリミングに安全なライブラリの作成については、[skill:dotnet-trimming] を参照してください。MAUI 固有の AOT については、[skill:dotnet-maui-aot] を参照してください。Blazor のコンポーネントパターンとアーキテクチャについては、[skill:dotnet-blazor-patterns](参考)を参照してください。Uno Platform のアーキテクチャについては、[skill:dotnet-uno-platform](参考)を参照してください。

相互参照:一般的な AOT パイプラインについては [skill:dotnet-native-aot]、トリミングの注釈については [skill:dotnet-trimming]、AOT に安全な設計パターンについては [skill:dotnet-aot-architecture]、AOT に安全なシリアル化については [skill:dotnet-serialization]、AOT を可能にするソースジェネレーターについては [skill:dotnet-csharp-source-generators]、Blazor のアーキテクチャについては [skill:dotnet-blazor-patterns](参考)、Uno Platform のパターンについては [skill:dotnet-uno-platform](参考)を参照してください。


ダウンロードサイズと実行速度

WASM AOT を判断するうえで、サイズと速度のトレードオフを理解することが重要です。

コンパイルモードダウンロードサイズ実行速度起動時間
IL インタープリター(AOT なし)最小最低最速
AOT(すべてのアセンブリ)最大最速遅い
AOT(選択的)+トリミングバランス型良好中程度
トリミングのみ(AOT なし)小中程度(JIT 解釈)速い

重要なポイント: トリミングは未使用の IL を削除してサイズを小さくします。AOT は、コンパイル済みのネイティブ WASM コードが同等の IL バイトコードより大きいため、成果物全体のサイズを増やします。ただし、AOT コンパイルされたコードは実行時の IL 解釈を省略するため、実行速度が大幅に向上します。

WASM AOT を使用する場合
  • CPU 負荷の高いワークロード: 画像処理、複雑な計算、データ変換
  • 予測可能なパフォーマンス: JIT の一時停止がなく、一貫した実行速度
  • ホットパス: パフォーマンス上重要なアセンブリのみを AOT コンパイルします(選択的 AOT)
WASM AOT を使用しない場合
  • 帯域幅が限られたユーザー: AOT によりダウンロードサイズが大幅に増加します
  • 単純な CRUD アプリ: UI 操作や API 呼び出しには IL 解釈で十分な速度が得られます
  • 迅速な反復開発: AOT コンパイルにより発行時間が大幅に増加します

Blazor WASM AOT

AOT を有効にする

<PropertyGroup>
  <RunAOTCompilation>true</RunAOTCompilation>
</PropertyGroup>
# Publish with AOT (required -- AOT only applies during publish)
dotnet publish -c Release

注:RunAOTCompilation は Blazor WASM のプロパティです(サーバーサイドの Native AOT 用である PublishAot ではありません)。AOT コンパイルは dotnet publish の実行時にのみ行われ、dotnet run や dotnet build では行われません。

遅延読み込みによる選択的 AOT

Blazor WASM AOT は、遅延読み込みされていないすべてのアセンブリをコンパイルします。AOT コンパイルするアセンブリを制御するには、重要度の低いアセンブリを遅延読み込み対象として指定します。これらのアセンブリは IL 解釈を使用します。

<PropertyGroup>
  <RunAOTCompilation>true</RunAOTCompilation>
</PropertyGroup>

<ItemGroup>
  
  <BlazorWebAssemblyLazyLoad Include="MyApp.Reporting.wasm" />
  <BlazorWebAssemblyLazyLoad Include="MyApp.Admin.wasm" />
  
</ItemGroup>
トリミングと AOT の併用

最適なバランスを得るには、トリミングと AOT の両方を使用します。

<PropertyGroup>
  
  <PublishTrimmed>true</PublishTrimmed>

  
  <RunAOTCompilation>true</RunAOTCompilation>

  
  <EnableTrimAnalyzer>true</EnableTrimAnalyzer>
</PropertyGroup>

発行パイプラインでは、まず未使用の IL をトリミングし、その後、残ったアセンブリをネイティブ WASM に AOT コンパイルします。これにより、トリミングのみの場合より大きく、トリミングなしの AOT の場合より小さい成果物を生成し、実行時のパフォーマンスを最大限に高められます。


Uno WASM AOT

Uno Platform 5 以降と .NET 8 以降では標準の .NET WASM ワークロードを使用するため、AOT の構成は Blazor WASM と同じです。

AOT の有効化(Uno 5+ / .NET 8+)

<PropertyGroup Condition="'$(TargetFramework)' == 'net8.0-browserwasm'">
  <RunAOTCompilation>true</RunAOTCompilation>
</PropertyGroup>

Uno.Wasm.Bootstrap を使用する古い Uno バージョンでは、Interpreter、InterpreterAndAOT、FullAOT モードを指定する独立した WasmShellMonoRuntimeExecutionMode プロパティがありました。.NET 8+ では、代わりに RunAOTCompilation を使用してください。

Uno WASM のトリミング
<PropertyGroup>
  <PublishTrimmed>true</PublishTrimmed>
  <TrimMode>link</TrimMode>
</PropertyGroup>

Uno Platform のアーキテクチャパターンについては、[skill:dotnet-uno-platform] を参照してください。


アセンブリの遅延読み込み

遅延読み込みでは、必要になるまでアセンブリのダウンロードを保留し、初回ダウンロードサイズを削減できます。AOT と組み合わせると(アセンブリごとのサイズが増加するため)、特に効果的です。

Blazor WASM の遅延読み込み

<ItemGroup>
  <BlazorWebAssemblyLazyLoad Include="MyApp.Reporting.wasm" />
  <BlazorWebAssemblyLazyLoad Include="MyApp.Admin.wasm" />
  <BlazorWebAssemblyLazyLoad Include="ChartLibrary.wasm" />
</ItemGroup>
// Load assemblies on demand in a component or router
@inject LazyAssemblyLoader LazyLoader

@code {
    private List<Assembly> _lazyLoadedAssemblies = new();

    private async Task LoadReportingModule()
    {
        var assemblies = await LazyLoader.LoadAssembliesAsync(new[]
        {
            "MyApp.Reporting.wasm"
        });
        _lazyLoadedAssemblies.AddRange(assemblies);
    }
}
ルーターによる遅延読み込み

@inject LazyAssemblyLoader LazyLoader

<Router AppAssembly="typeof(App).Assembly"
        AdditionalAssemblies="@_lazyLoadedAssemblies"
        OnNavigateAsync="@OnNavigateAsync">
    <Navigating>
        <div class="loading">Loading module...</div>
    </Navigating>
</Router>

@code {
    private List<Assembly> _lazyLoadedAssemblies = new();

    private async Task OnNavigateAsync(NavigationContext context)
    {
        if (context.Path.StartsWith("admin"))
        {
            var assemblies = await LazyLoader.LoadAssembliesAsync(new[]
            {
                "MyApp.Admin.wasm"
            });
            _lazyLoadedAssemblies.AddRange(assemblies);
        }
        else if (context.Path.StartsWith("reports"))
        {
            var assemblies = await LazyLoader.LoadAssembliesAsync(new[]
            {
                "MyApp.Reporting.wasm"
            });
            _lazyLoadedAssemblies.AddRange(assemblies);
        }
    }
}
遅延読み込みの戦略
戦略初回読み込み機能の読み込み最適な用途
遅延読み込みなしすべて一度に即時小規模アプリ(合計 <5 MB)
ルートベースの遅延読み込みコアのみナビゲーション時複数モジュールのアプリ
機能ベースの遅延読み込みコアのみ必要に応じてオプション機能のあるアプリ

Brotli の事前圧縮

Brotli の事前圧縮により、WASM のダウンロードサイズを 60-80% 削減できます。Blazor WASM は、発行時に Brotli 圧縮ファイルを自動生成します。

仕組み

dotnet publish の実行中に、Blazor WASM は _framework/ 内のすべての静的ファイルについて、.br(Brotli)および .gz(gzip)圧縮版を生成します。ブラウザーが対応している場合、Web サーバーは事前圧縮ファイルを配信します。

# After publish, check compressed sizes
ls -la bin/Release/net8.0/publish/wwwroot/_framework/

# You'll see:
# MyApp.wasm       (original)
# MyApp.wasm.br    (Brotli compressed, ~60-80% smaller)
# MyApp.wasm.gz    (gzip compressed, ~50-70% smaller)
サーバーの構成

Web サーバーで、事前圧縮ファイルを配信するように構成する必要があります。ほとんどの Blazor ホスティング構成では、これが自動的に処理されます。

ASP.NET Core ホスティング:

// In the server project hosting Blazor WASM
app.UseBlazorFrameworkFiles();
app.UseStaticFiles();
// Blazor framework files are served with compression headers automatically

Nginx:

location /_framework/ {
    # Serve Brotli-compressed files when available
    gzip_static on;
    brotli_static on;

    # Set correct MIME types
    types {
        application/wasm wasm;
    }

    # Cache aggressively (files are content-hashed)
    add_header Cache-Control "public, max-age=31536000, immutable";
}

Azure Static Web Apps / GitHub Pages:

Accept-Encoding: br ヘッダーが存在する場合、事前圧縮された .br ファイルが自動的に配信されます。

圧縮の効果
コンテンツ元のサイズBrotli(.br)削減率
.NET WASM ランタイム~2.5 MB~0.8 MB~68%
アプリのアセンブリ(IL)さまざま約70%縮小~70%
アプリのアセンブリ(AOT)さまざま約65%縮小~65%
JavaScript グルーコード~100 KB~25 KB~75%
圧縮の無効化(通常は不要)

<PropertyGroup>
  <BlazorEnableCompression>false</BlazorEnableCompression>
</PropertyGroup>

WASM サイズ最適化チェックリスト

  1. トリミングを有効にする -- AOT コンパイル前に未使用の IL を削除します
  2. 遅延読み込みを使用する -- 重要度の低いアセンブリの読み込みを保留します
  3. Brotli の事前圧縮を有効にする -- 転送サイズを 60-80% 削減します(デフォルトで有効)
  4. 選択的に AOT を使用する -- パフォーマンスが重要なアセンブリのみを AOT コンパイルします
  5. カルチャ固有の書式設定が不要な場合は、不変のグローバリゼーションを有効にする:
    <PropertyGroup>
      <InvariantGlobalization>true</InvariantGlobalization>
    </PropertyGroup>
    
  6. 未使用のフレームワーク機能を削除する:
    <PropertyGroup>
      
      <EventSourceSupport>false</EventSourceSupport>
      <HttpActivityPropagationSupport>false</HttpActivityPropagationSupport>
    </PropertyGroup>
    
  7. 圧縮ファイルが配信されていることを確認する -- ブラウザーの DevTools の Network タブで content-encoding: br を確認します

エージェントが注意すべき点

  1. RunAOTCompilation と PublishAot を混同しないでください。 Blazor WASM は WASM AOT に RunAOTCompilation を使用します。PublishAot はサーバー側の Native AOT 用で、異なる種類のバイナリを生成します。
  2. AOT によって WASM のダウンロードサイズが小さくなると思い込まないでください。 AOT では、ネイティブ WASM コードが IL バイトコードより大きいため、成果物のサイズが増加します。サイズの削減にはトリミングを、実行時の速度向上には AOT を使用してください。
  3. AOT のテスト時に発行を忘れないでください。 WASM AOT は dotnet publish の実行時のみ動作し、dotnet run では動作しません。デバッグビルドでは常に IL インタープリターが使用されます。
  4. 起動時に必要なアセンブリを遅延読み込みしないでください。 初回ナビゲーション後にアクセスする機能のアセンブリのみを遅延読み込みしてください。遅延読み込みアセンブリをロードすると、ネットワークリクエストが発生します。
  5. Brotli 圧縮の確認を省略しないでください。 Web サーバーが .br ファイルを配信することを確認してください。圧縮がない場合、WASM のダウンロードサイズは必要以上に 3-5 倍になります。ブラウザーの DevTools で content-encoding: br ヘッダーを確認してください。
  6. ダウンロードサイズが重要な場合、すべてのアセンブリを AOT コンパイルしないでください。 BlazorWebAssemblyLazyLoad を使用して、重要度の低いアセンブリの読み込みを保留してください。遅延読み込みされたアセンブリでは、AOT の代わりに IL インタープリターが使用されます。

参考資料

コメント