بنقرة واحدة
dotnet-aot-wasm
Compiles .NET to WebAssembly AOT. Blazor/Uno WASM, size vs speed, lazy loading, Brotli.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Compiles .NET to WebAssembly AOT. Blazor/Uno WASM, size vs speed, lazy loading, Brotli.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Rulesync CLI tool documentation - unified AI rule file management for various AI coding tools
Publishes .NET artifacts from Azure DevOps. NuGet push, containers to ACR, pipeline artifacts.
Reads and modifies SDK-style .csproj files. PropertyGroup, ItemGroup, CPM, props.
Publishes .NET artifacts from GitHub Actions. NuGet push, container images, signing, SBOM.
Builds event-driven systems. Pub/sub, competing consumers, DLQ, sagas, delivery guarantees.
Adds fault tolerance. Polly v8 + MS.Extensions.Http.Resilience, retry/circuit breaker/timeout.
| name | dotnet-aot-wasm |
| description | Compiles .NET to WebAssembly AOT. Blazor/Uno WASM, size vs speed, lazy loading, Brotli. |
| allowed-tools | ["Read","Grep","Glob","Bash","Write","Edit"] |
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.
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).
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.
<!-- Blazor WASM .csproj -->
<PropertyGroup>
<RunAOTCompilation>true</RunAOTCompilation>
</PropertyGroup>
# 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.
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:
<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>
For the best balance, use both trimming and AOT:
<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 Platform 5+ with .NET 8+ uses the standard .NET WASM workload, so the AOT configuration is the same as Blazor WASM.
<!-- 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.
<PropertyGroup>
<PublishTrimmed>true</PublishTrimmed>
<TrimMode>link</TrimMode>
</PropertyGroup>
See [skill:dotnet-uno-platform] for Uno Platform architecture patterns.
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).
<!-- Mark assemblies for lazy loading in .csproj -->
<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);
}
}
<!-- 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);
}
}
}
| 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 reduces WASM download size by 60-80%. Blazor WASM automatically generates Brotli-compressed files during publish.
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.
# 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)
The web server must be configured to serve pre-compressed files. Most Blazor hosting setups handle this automatically.
ASP.NET Core hosting:
// 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:
Pre-compressed .br files are served automatically when the Accept-Encoding: br header is present.
| 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% |
<!-- Disable Brotli pre-compression -->
<PropertyGroup>
<BlazorEnableCompression>false</BlazorEnableCompression>
</PropertyGroup>
<PropertyGroup>
<InvariantGlobalization>true</InvariantGlobalization>
</PropertyGroup>
<PropertyGroup>
<!-- Disable features you don't use -->
<EventSourceSupport>false</EventSourceSupport>
<HttpActivityPropagationSupport>false</HttpActivityPropagationSupport>
</PropertyGroup>
content-encoding: brRunAOTCompilation with PublishAot. Blazor WASM uses RunAOTCompilation for WASM AOT. PublishAot is for server-side Native AOT and produces a different kind of binary.dotnet publish, not dotnet run. Debug builds always use IL interpretation..br files. Without compression, WASM downloads are 3-5x larger than necessary. Check browser DevTools for content-encoding: br header.BlazorWebAssemblyLazyLoad to defer non-critical assemblies -- lazy-loaded assemblies use IL interpretation instead of AOT.