本文へ移動
cccskills
無料GitHub で公開

dotnet-aot-wasm

Compiles .NET to WebAssembly AOT. Blazor/Uno WASM, size vs speed, lazy loading, Brotli.

インストール方法を見る

含まれるファイル(1)

  • SKILL.md14.1 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

dotnet-aot-wasm

WebAssembly AOT compilation for Blazor WASM and Uno WASM applications: compilation pipeline, download size vs runtime speed tradeoffs, trimming interplay, lazy loading assemblies, and Brotli pre-compression for download optimization.

Version assumptions: .NET 8.0+ baseline. Blazor WASM AOT shipped in .NET 6 and has been refined through .NET 8-10. Uno WASM uses a similar compilation pipeline with Uno-specific tooling.

Important tradeoff: Trimming and AOT have opposite effects on WASM artifact size. Trimming reduces download size by removing unused code. AOT increases artifact size (native WASM code is larger than IL) but improves runtime execution speed. Use both together for the best balance.

Scope

  • Download size vs runtime speed tradeoff analysis
  • Blazor WASM AOT (RunAOTCompilation, selective AOT)
  • Uno WASM AOT (.NET 8+ standard workload)
  • Lazy loading assemblies for size reduction
  • Brotli pre-compression for download optimization
  • WASM size optimization checklist

Out of scope

  • Native AOT for server-side .NET -- see [skill:dotnet-native-aot]
  • AOT-first design patterns -- see [skill:dotnet-aot-architecture]
  • Trim-safe library authoring -- see [skill:dotnet-trimming]
  • MAUI-specific AOT -- see [skill:dotnet-maui-aot]
  • Blazor hosting models and render modes -- see [skill:dotnet-blazor-patterns]
  • Blazor component lifecycle and JS interop -- see [skill:dotnet-blazor-components]
  • Uno Platform architecture -- see [skill:dotnet-uno-platform]

Cross-references: [skill:dotnet-native-aot] for general AOT pipeline, [skill:dotnet-trimming] for trimming annotations, [skill:dotnet-aot-architecture] for AOT-safe design patterns, [skill:dotnet-serialization] for AOT-safe serialization, [skill:dotnet-csharp-source-generators] for source gen as AOT enabler, [skill:dotnet-blazor-patterns] for Blazor architecture (soft), [skill:dotnet-uno-platform] for Uno Platform patterns (soft).


Download Size vs Runtime Speed

Understanding the size/speed tradeoff is critical for WASM AOT decisions:

Compilation ModeDownload SizeRuntime SpeedStartup Time
IL interpreter (no AOT)SmallestSlowestFastest startup
AOT (all assemblies)LargestFastestSlower startup
AOT (selective) + trimmingBalancedGoodModerate
Trimmed only (no AOT)SmallModerate (JIT interpretation)Fast

Key insight: Trimming reduces size by removing unused IL. AOT increases total artifact size because compiled native WASM code is larger than the equivalent IL bytecode. However, AOT-compiled code executes significantly faster because it skips IL interpretation at runtime.

When to Use WASM AOT

  • CPU-intensive workloads: Image processing, complex calculations, data transformation
  • Predictable performance: Consistent execution speed without JIT pauses
  • Hot paths: AOT-compile only performance-critical assemblies (selective AOT)

When to Skip WASM AOT

  • Bandwidth-constrained users: AOT increases download size significantly
  • Simple CRUD apps: IL interpretation is fast enough for UI interactions and API calls
  • Rapid iteration: AOT compilation adds significant publish time

Blazor WASM AOT

Enabling AOT


<!-- Blazor WASM .csproj -->
<PropertyGroup>
  <RunAOTCompilation>true</RunAOTCompilation>
</PropertyGroup>

```csharp

```bash

# Publish with AOT (required -- AOT only applies during publish)
dotnet publish -c Release

```bash

Note: `RunAOTCompilation` is the Blazor WASM property (not `PublishAot` which is for server-side Native AOT). AOT
compilation only happens during `dotnet publish`, not during `dotnet run` or `dotnet build`.

### Selective AOT via Lazy Loading

Blazor WASM AOT compiles all non-lazy-loaded assemblies. To control which assemblies are AOT-compiled, mark non-critical
assemblies as lazy-loaded -- they will use IL interpretation instead:

```xml

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

<ItemGroup>
  <!-- These assemblies are NOT AOT-compiled (loaded on demand via IL interpreter) -->
  <BlazorWebAssemblyLazyLoad Include="MyApp.Reporting.wasm" />
  <BlazorWebAssemblyLazyLoad Include="MyApp.Admin.wasm" />
  <!-- All other assemblies (MyApp.Core, MyApp.Calculations, etc.) ARE AOT-compiled -->
</ItemGroup>

```text

### Trimming + AOT Together

For the best balance, use both trimming and AOT:

```xml

<PropertyGroup>
  <!-- Trimming reduces unused code (smaller download) -->
  <PublishTrimmed>true</PublishTrimmed>

  <!-- AOT compiles remaining code to native WASM (faster execution) -->
  <RunAOTCompilation>true</RunAOTCompilation>

  <!-- Detailed warnings during development -->
  <EnableTrimAnalyzer>true</EnableTrimAnalyzer>
</PropertyGroup>

```text

The publish pipeline runs: trim unused IL first, then AOT-compile the remaining assemblies to native WASM. This produces
an artifact that is larger than trimmed-only but smaller than AOT-without-trimming, with the best runtime performance.

---

## Uno WASM AOT

Uno Platform 5+ with .NET 8+ uses the standard .NET WASM workload, so the AOT configuration is the same as Blazor WASM.

### Enabling AOT (Uno 5+ / .NET 8+)

```xml

<!-- Uno WASM head .csproj -->
<PropertyGroup Condition="'$(TargetFramework)' == 'net8.0-browserwasm'">
  <RunAOTCompilation>true</RunAOTCompilation>
</PropertyGroup>

```csharp

Older Uno versions using `Uno.Wasm.Bootstrap` had a separate `WasmShellMonoRuntimeExecutionMode` property with
`Interpreter`, `InterpreterAndAOT`, and `FullAOT` modes. On .NET 8+, use `RunAOTCompilation` instead.

### Trimming in Uno WASM

```xml

<PropertyGroup>
  <PublishTrimmed>true</PublishTrimmed>
  <TrimMode>link</TrimMode>
</PropertyGroup>

```text

See [skill:dotnet-uno-platform] for Uno Platform architecture patterns.

---

## Lazy Loading Assemblies

Lazy loading defers downloading assemblies until they are needed, reducing initial download size. This is especially
effective when combined with AOT (which increases per-assembly size).

### Blazor WASM Lazy Loading

```xml

<!-- Mark assemblies for lazy loading in .csproj -->
<ItemGroup>
  <BlazorWebAssemblyLazyLoad Include="MyApp.Reporting.wasm" />
  <BlazorWebAssemblyLazyLoad Include="MyApp.Admin.wasm" />
  <BlazorWebAssemblyLazyLoad Include="ChartLibrary.wasm" />
</ItemGroup>

```text

```csharp

// 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);
    }
}

```text

### Router-Based Lazy Loading

```csharp

<!-- App.razor -->
@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);
        }
    }
}

```text

### Lazy Loading Strategy

| Strategy                   | Initial Load | Feature Load  | Best For                    |
| -------------------------- | ------------ | ------------- | --------------------------- |
| No lazy loading            | All at once  | Instant       | Small apps (<5 MB total)    |
| Route-based lazy loading   | Core only    | On navigation | Multi-module apps           |
| Feature-based lazy loading | Core only    | On demand     | Apps with optional features |

---

## Brotli Pre-Compression

Brotli pre-compression reduces WASM download size by 60-80%. Blazor WASM automatically generates Brotli-compressed files
during publish.

### How It Works

During `dotnet publish`, Blazor WASM generates `.br` (Brotli) and `.gz` (gzip) compressed versions of all static files
in `_framework/`. The web server serves the pre-compressed file when the browser supports it.

```bash

# 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)

```text

### Server Configuration

The web server must be configured to serve pre-compressed files. Most Blazor hosting setups handle this automatically.

**ASP.NET Core hosting:**

```csharp

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

```text

**Nginx:**

```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";
}

```text

**Azure Static Web Apps / GitHub Pages:**

Pre-compressed `.br` files are served automatically when the `Accept-Encoding: br` header is present.

### Compression Impact

| Content              | Original | Brotli (.br) | Reduction |
| -------------------- | -------- | ------------ | --------- |
| .NET WASM runtime    | ~2.5 MB  | ~0.8 MB      | ~68%      |
| App assemblies (IL)  | varies   | ~70% smaller | ~70%      |
| App assemblies (AOT) | varies   | ~65% smaller | ~65%      |
| JavaScript glue code | ~100 KB  | ~25 KB       | ~75%      |

### Disabling Compression (Rarely Needed)

```xml

<!-- Disable Brotli pre-compression -->
<PropertyGroup>
  <BlazorEnableCompression>false</BlazorEnableCompression>
</PropertyGroup>

```text

---

## WASM Size Optimization Checklist

1. **Enable trimming** -- removes unused IL before AOT compilation
2. **Use lazy loading** -- defer non-critical assemblies
3. **Enable Brotli pre-compression** -- 60-80% reduction in transfer size (on by default)
4. **Use selective AOT** -- only AOT-compile performance-critical assemblies
5. **Enable invariant globalization** if culture-specific formatting is not needed:

   ```xml

   <PropertyGroup>
     <InvariantGlobalization>true</InvariantGlobalization>
   </PropertyGroup>

  1. Remove unused framework features:

    
    <PropertyGroup>
      <!-- Disable features you don't use -->
      <EventSourceSupport>false</EventSourceSupport>
      <HttpActivityPropagationSupport>false</HttpActivityPropagationSupport>
    </PropertyGroup>
    
    
  2. Verify compression is served -- check browser DevTools Network tab for content-encoding: br


Agent Gotchas

  1. Do not confuse RunAOTCompilation with PublishAot. Blazor WASM uses RunAOTCompilation for WASM AOT. PublishAot is for server-side Native AOT and produces a different kind of binary.
  2. Do not assume AOT reduces WASM download size. AOT increases artifact size because native WASM code is larger than IL bytecode. Use trimming to reduce size and AOT to improve runtime speed.
  3. Do not forget to publish when testing AOT. WASM AOT only runs during dotnet publish, not dotnet run. Debug builds always use IL interpretation.
  4. Do not lazy-load assemblies that are needed at startup. Only lazy-load assemblies for features accessed after initial navigation. Loading a lazy assembly triggers a network request.
  5. Do not skip Brotli compression verification. Ensure your web server serves .br files. Without compression, WASM downloads are 3-5x larger than necessary. Check browser DevTools for content-encoding: br header.
  6. Do not AOT-compile all assemblies when download size matters. Use BlazorWebAssemblyLazyLoad to defer non-critical assemblies -- lazy-loaded assemblies use IL interpretation instead of AOT.

Code Navigation (Serena MCP)

Primary approach: Use Serena symbol operations for efficient code navigation:

  1. Find definitions: serena_find_symbol instead of text search
  2. Understand structure: serena_get_symbols_overview for file organization
  3. Track references: serena_find_referencing_symbols for impact analysis
  4. Precise edits: serena_replace_symbol_body for clean modifications

When to use Serena vs traditional tools:

  • ✅ Use Serena: Navigation, refactoring, dependency analysis, precise edits
  • ✅ Use Read/Grep: Reading full files, pattern matching, simple text operations
  • ✅ Fallback: If Serena unavailable, traditional tools work fine

Example workflow:

# Instead of:
Read: src/Services/OrderService.cs
Grep: "public void ProcessOrder"

# Use:
serena_find_symbol: "OrderService/ProcessOrder"
serena_get_symbols_overview: "src/Services/OrderService.cs"

References

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Patterns and techniques for evaluating and improving AI agent outputs.

日本語の概要は準備中です。原文の説明を表示しています。

rudironsoni/Synaxis22026年3月17日 更新

Comprehensive AI prompt engineering safety review and improvement prompt. Analyzes prompts for safety, bias, security vulnerabilities, and effectiveness while providing detailed improvement recommendations.

日本語の概要は準備中です。原文の説明を表示しています。

rudironsoni/Synaxis22026年3月17日 更新

Use when user requests research requiring multiple sources, comprehensive analysis, or synthesis across topics - technical research, domain knowledge gathering, market analysis, or learning about complex subjects

日本語の概要は準備中です。原文の説明を表示しています。

rudironsoni/Synaxis22026年3月17日 更新

deep-wiki

無料

AI-powered wiki generation for code repositories with commands, agents, and skills

日本語の概要は準備中です。原文の説明を表示しています。

rudironsoni/Synaxis22026年3月17日 更新

Use when building .NET 10 or C# 14 applications; when using minimal APIs, modular monolith patterns, or feature folders; when implementing HTTP resilience, Options pattern, Channels, or validation; when seeing outdated patterns like old extension method syntax

日本語の概要は準備中です。原文の説明を表示しています。

rudironsoni/Synaxis22026年3月17日 更新

Implements accessible .NET UI. SemanticProperties, ARIA, AutomationPeer, testing per platform.

日本語の概要は準備中です。原文の説明を表示しています。

rudironsoni/Synaxis22026年3月17日 更新

rudironsoni のスキルをすべて見る

このスキルの問題を報告する