Is uw Blazor-app traag? 7 oorzaken en hoe u ze oplost

Uw Blazor-app hapert bij elke klik, een tabel bevriest of het servergeheugen groeit? De zeven meest voorkomende oorzaken, met code voor en na.

Vlado Pandžić

Vlado Pandžić · Oprichter · Senior .NET-architect
Gepubliceerd · 4 min lezen

In het begin vliegt een Blazor-applicatie. Een paar schermen, weinig data, alles reageert meteen. Een jaar later hapert een klik op een knop, bevriest de ordertabel een paar seconden, en gebruikt de server in de loop van de dag steeds meer geheugen.

Blazor is zelden alleen de schuldige. Het is bijna altijd een van deze zeven oorzaken, en ze zijn allemaal op te lossen zonder de applicatie te herschrijven. Elke oorzaak staat hier met code, voor .NET 10.

Eerst: meet wat er rendert

De meest voorkomende verrassing is hoe vaak een component rendert. Een tijdelijke log laat het in een minuut zien:

protected override void OnAfterRender(bool firstRender)
    => Logger.LogDebug("{Component} rendered", GetType().Name);   // tijdelijk, alleen tijdens het meten

Zet één klik vijftig regels in de log, dan hebt u probleem nummer één gevonden.

1. Alles rendert opnieuw bij elke klik

Blazor rendert een kind opnieuw als zijn parameters veranderen. Maar is een parameter een complex object, zoals een hele order, dan kan Blazor niet weten of daarin iets is veranderd, en rendert het elke keer. Eenvoudige types zoals int en string laten de component pas opnieuw renderen als hun waarde verandert.

@* voor: het hele object, dus de rij rendert bij elke wijziging van de ouder *@
<OrderRow Order="order" />

@* na: alleen wat de rij toont *@
<OrderRow Number="@order.Number" Customer="@order.CustomerName" Total="@order.Total" />

Als dat niet kan, kan de component zelf bepalen of hij rendert:

private int lastVersion;

protected override bool ShouldRender()
{
    var changed = Order.Version != lastVersion;   // alleen renderen als de order echt is veranderd
    lastVersion = Order.Version;
    return changed;
}

2. Lijsten zonder @key

Als een lijst verandert, vergelijkt Blazor zonder @key de rijen op positie. Eén rij die bovenaan wordt ingevoegd, betekent dat alle rijen eronder opnieuw renderen, en toestand binnen de rijen kan in de verkeerde rij belanden.

@foreach (var order in orders)
{
    <OrderRow @key="order.Id" Number="@order.Number" Total="@order.Total" />
}

3. Tabellen met duizenden rijen

Vijfduizend rijen in één keer gerenderd betekent vijfduizend componenten in het geheugen en op het scherm, terwijl de gebruiker er twintig ziet. Virtualize rendert alleen wat zichtbaar is:

<Virtualize Items="orders" Context="order">
    <OrderRow @key="order.Id" Number="@order.Number" Total="@order.Total" />
</Virtualize>

QuickGrid doet hetzelfde met Virtualize="true", en voor echt grote hoeveelheden data kunnen beide de rijen stukje bij beetje van de server ophalen.

4. Data wordt twee keer geladen

Met prerendering draait OnInitializedAsync twee keer: één keer op de server voor de eerste weergave, en nog een keer als de component interactief wordt. Dat betekent twee identieke databasequeries en een flikkering op het scherm. In .NET 10 lost één attribuut dat op:

@code {
    [PersistentState]
    public List<OrderSummary>? Orders { get; set; }

    protected override async Task OnInitializedAsync()
    {
        Orders ??= await OrderService.GetOpenAsync();   // de tweede keer is de data er al
    }
}

5. StateHasChanged te vaak

Een component die prijzen, statussen of berichten in realtime volgt, komt al snel op tientallen renders per seconde. De gebruiker ziet geen verschil tussen 4 en 40 verversingen per seconde, maar de server en de browser wel degelijk.

protected override void OnInitialized()
{
    Prices.Changed += OnPriceChanged;
    renderTimer = new Timer(_ =>
    {
        if (!dirty) return;
        dirty = false;
        InvokeAsync(StateHasChanged);                  // hooguit vier renders per seconde
    }, null, 250, 250);
}

private void OnPriceChanged(object? sender, PriceChangedEventArgs e) => dirty = true;  // alleen de wijziging noteren

6. Servergeheugen dat alleen maar groeit

Een component die zich abonneert op een event of een timer start en dat nooit opzegt, sterft nooit. Op Blazor Server betekent dat dat het geheugen groeit met elke gebruiker en elk geopend scherm, tot de volgende herstart.

@implements IDisposable

@code {
    public void Dispose()
    {
        Prices.Changed -= OnPriceChanged;              // zonder dit blijft de component in het geheugen
        renderTimer?.Dispose();
    }
}

7. De verkeerde rendermodus voor het scherm

In .NET 10 kan elke pagina een eigen rendermodus hebben. Interactive Server is uitstekend voor interne schermen op een goed netwerk, maar op een slechte verbinding wacht elke klik op het netwerk. Pagina’s die alleen worden gelezen, hebben helemaal geen interactiviteit nodig.

@* MonthlyReport.razor: alleen lezen, statisch renderen zonder verbinding met de server *@
@page "/reports/monthly"

@* Orders.razor: een interactief scherm *@
@page "/orders"
@rendermode InteractiveServer

Welke modus voor welk scherm staat in de tabel op de pagina Blazor-specialisatie.

In welke volgorde

  1. MetenHoe vaak wat rendert
  2. OpsplitsenKleinere componenten, eenvoudige parameters
  3. VirtualiserenGrote lijsten en tabellen
  4. OpruimenDispose en de rendermodus

Vaak is een traag Blazor-scherm helemaal geen Blazor-probleem, maar een probleem met de queries erachter. Laadt een scherm lang maar rendert het weinig, lees dan het artikel over EF Core-performance.

Hoe wij werken

ProCoding is een .NET-studio uit Split, Kroatië, en we brengen Blazor sinds 2020 in productie, van software voor het bouwen van elektrische auto’s tot het aansturen van batterijopslag. Een Blazor health check vindt welke van deze oorzaken uw applicatie afremt en levert een geprioriteerde lijst met verbeteringen. De eerste stap is een gratis gesprek van 30 minuten.

Bronnen

Dit artikel is alleen algemene informatie en geen juridisch, fiscaal, financieel of ander professioneel advies. Scenario’s, voorbeelden en berekeningen zijn ter illustratie. Gebruiksvoorwaarden en disclaimer.

Gerelateerde artikelen

© 2026 ProCoding — Alle rechten voorbehouden.Colofon en privacyDisclaimerSplit, Kroatië