Compilare Ahead-Of-Time (Native AOT) în .NET 8 și .NET 9: Microservicii Fără JIT în C# (.NET)

.NET BCL și CLI-ul dotnet .NET 8 / .NET 9

Ghid complet pentru Native AOT în .NET 8 și .NET 9: generarea de binare mașină native fără runtime JIT, reguli de compatibilitate fără reflexie dinamică și containere Docker ultra-mici de sub 20 MB.

Sintaxă C#
<PublishAot>true</PublishAot> | dotnet publish -c Release -r linux-x64

În mod tradițional, rularea unei aplicații .NET necesită prezența mașinii virtuale CLR și a compilatorului JIT (Just-In-Time) pe server. În medii containerizate (Kubernetes, AWS Lambda, Google Cloud Run), prezența runtime-ului complet mărește dimensiunea imaginilor Docker și întârzie pornirea primului container (Cold Start).

Native AOT (Ahead-Of-Time), stabilizat pentru ASP.NET Core în .NET 8 și extins în .NET 9, compilează codul C# direct în binar nativ de sistem de operare (fără CIL intermediar și fără JIT la runtime). Binarul include doar codul strict utilizat de aplicație, pornind în sub 5 milisecunde cu o amprentă de memorie de sub 15-20 MB!

Activarea Native AOT în Fișierul de Proiect (.csproj)
<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>

    <!-- Activarea compilării native AOT: -->
    <PublishAot>true</PublishAot>
    
    <!-- Curățarea agresivă a codului nefolosit (Trimming): -->
    <OptimizationPreference>Size</OptimizationPreference>
  </PropertyGroup>
</Project>

Serializarea JSON Compatibilă cu AOT

Deoarece Native AOT interzice reflexia dinamică pe proprietăți neștiute la compilare, serializatorul System.Text.Json folosește Source Generators:

// 1. Definim contextul de serializare la compilare:
[JsonSerializable(typeof(Produs))]
[JsonSerializable(typeof(List<Produs>))]
internal partial class AppJsonSerializerContext : JsonSerializerContext {}

// 2. Înregistrarea în Minimal API:
var builder = WebApplication.CreateSlimBuilder(args);
builder.Services.ConfigureHttpJsonOptions(options => {
    options.SerializerOptions.TypeInfoResolver = AppJsonSerializerContext.Default;
});

var app = builder.Build();
app.MapGet("/produse", () => new Produs(1, "Laptop", 4500.0));
app.Run();

Comanda de Publicare

dotnet publish -c Release -r linux-x64 --self-contained
# Rezultat: Un singur fișier binar executabil nativ compact, fără dependențe externe de .NET!