Claude
Skills
Sign in
Back

dotnet-aot-wasm

Included with Lifetime
$97 forever

AOT-compiling for WebAssembly. Blazor/Uno WASM AOT, size vs speed, lazy loading, Brotli.

General

What this skill does


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

**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 component patterns and architecture -- see [skill:dotnet-blazor-patterns] (soft). Uno Platform architecture -- see [skill:dotnet-uno-platform] (soft).

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 Mode | Download Size | Runtime Speed | Startup Time |
|-----------------|---------------|---------------|-------------|
| IL interpreter (no AOT) | Smallest | Slowest | Fastest startup |
| AOT (all assemblies) | **Largest** | Fastest | Slower startup |
| AOT (selective) + trimming | Balanced | Good | Moderate |
| Trimmed only (no AOT) | Small | Moderate (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

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

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

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>
```

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

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>
```

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>
```

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>
```

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

### 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);
        }
    }
}
```

### 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 dur
Files: 1
Size: 12.4 KB
Complexity: 15/100
Category: General

Related in General