Angular @defer in 2026: Declaratief Lazy Loading voor Snellere Applicaties
Beheers Angular @defer-blokken voor declaratief lazy loading. Diepgaande analyse van triggers, prefetching, incrementele hydratie, SSR-gedrag en performancepatronen uit de praktijk.

Angular @defer-blokken bieden een oplossing voor een probleem dat routergebaseerd lazy loading nooit kon adresseren: het on-demand laden van individuele componenten, directives en pipes zonder de applicatie te herstructureren in afzonderlijke routes. Geintroduceerd in Angular 17 en gestabiliseerd in de loop van Angular 22, transformeert @defer wat voorheen dynamische imports, *ngIf-vlaggen en webpack-configuratie vereiste tot een enkel declaratief templateblok.
@defer instrueert de Angular-compiler om ingepakte componenten af te splitsen in afzonderlijke JavaScript-chunks, die pas worden geladen wanneer een triggerconditie wordt geactiveerd. De browser downloadt minder JavaScript bij de eerste lading, wat Largest Contentful Paint (LCP) en Time to First Byte (TTFB) verbetert zonder handmatige code-splittingconfiguratie.
Hoe @defer onder de motorkap werkt
Wanneer de Angular-compiler een @defer-blok tegenkomt, extraheert deze elke standalone component, directive en pipe binnenin het blok naar een afzonderlijke chunk. De hoofdbundel wordt verzonden zonder deze afhankelijkheden. Tijdens runtime evalueert Angular de triggerconditie en haalt de chunk op via een dynamische import()-aanroep.
Het blok ondersteunt vier subblokken die bepalen wat de gebruiker ziet tijdens de laadcyclus:
@defer (on viewport) {
<analytics-dashboard />
} @placeholder {
<div class="h-64 bg-muted animate-pulse"></div>
} @loading (minimum 200ms) {
<loading-spinner />
} @error {
<p>Failed to load the dashboard. Please refresh.</p>
}@placeholder wordt gerenderd voordat de trigger wordt geactiveerd. @loading verschijnt terwijl de chunk wordt gedownload, met een optionele minimum-duur om flikkering te voorkomen. @error vangt netwerkfouten of chunkfouten op. De parameter minimum op @loading voorkomt een korte flits van de spinner wanneer de chunk snel vanuit de cache wordt geladen.
Een belangrijke beperking: elke afhankelijkheid binnen @defer moet standalone zijn. Niet-standalone componenten die in een NgModule zijn gedeclareerd, kunnen niet worden uitgesteld en worden ongeacht de @defer-wrapper eager geladen.
Triggertypes: bepalen wanneer componenten worden geladen
Angular biedt zeven ingebouwde triggers, elk gericht op een andere laadstrategie. Meerdere triggers kunnen worden gecombineerd met puntkomma's en worden als OR-condities geevalueerd.
// Loads when the browser goes idle (default)
@defer {
<recommendation-engine />
}
// Loads when the element enters the viewport
@defer (on viewport) {
<customer-reviews [productId]="product.id" />
}
// Loads on click or keydown
@defer (on interaction) {
<product-configurator />
} @placeholder {
<button>Configure this product</button>
}
// Loads on mouseenter or focusin
@defer (on hover) {
<quick-preview />
}
// Loads after 3 seconds
@defer (on timer(3s)) {
<chat-widget />
}
// Loads immediately after initial render
@defer (on immediate) {
<notification-center />
}De trigger on viewport maakt intern gebruik van de Intersection Observer API. De trigger on idle delegeert naar requestIdleCallback, waardoor het de veiligste standaardkeuze is voor content onder de vouw. De trigger on timer accepteert duren in milliseconden (500ms) of seconden (3s).
De when-trigger voor reactieve condities
Naast event-gebaseerde triggers accepteert when elke booleaanse expressie, inclusief signallezingen:
export class DashboardComponent {
showAdvanced = signal(false);
}
// dashboard.component.html
@defer (when showAdvanced()) {
<advanced-analytics />
} @placeholder {
<button (click)="showAdvanced.set(true)">Show advanced analytics</button>
}Het combineren van on en when is geldig. Angular behandelt deze als OR: het blok wordt geladen wanneer aan een van beide condities wordt voldaan.
Prefetching: downloaden en weergeven ontkoppelen
Prefetching ontkoppelt het moment waarop de chunk wordt gedownload van het moment waarop het component wordt gerenderd. Dit elimineert waargenomen vertraging door het JavaScript op te halen voordat de gebruiker het activeert.
@defer (on interaction; prefetch on idle) {
<account-settings />
} @placeholder {
<button>Open settings</button>
}In dit patroon downloadt de browser de account-settings-chunk tijdens inactieve tijd. Wanneer de gebruiker klikt, wordt het component onmiddellijk gerenderd omdat de code al beschikbaar is. Prefetching accepteert dezelfde triggertypes als de hoofd-on-clausule.
Een veelgebruikt patroon voor dashboards: zware componenten prefetchen tijdens idle-tijd terwijl de rendering wordt uitgesteld tot het element de viewport bereikt.
@defer (on viewport; prefetch on idle) {
<chart-widget [data]="salesData()" />
} @placeholder (minimum 100ms) {
<div class="h-48 bg-muted rounded-none"></div>
}De minimum op @placeholder voorkomt een layoutflits wanneer de gebruiker snel scrollt en het uitgestelde component vrijwel onmiddellijk wordt geladen.
Klaar om je Angular gesprekken te halen?
Oefen met onze interactieve simulatoren, flashcards en technische tests.
@defer en server-side rendering
Op de server rendert @defer-blokken standaard de @placeholder-inhoud. Het uitgestelde component wordt nooit server-side gerenderd. Dit gedrag is opzettelijk: het downloaden van chunks heeft alleen zin in een browsercontext.
Voor SEO-kritieke content betekent dit dat @placeholder betekenisvolle HTML moet bevatten, niet slechts een spinner:
@defer (on viewport) {
<comment-section [postId]="post.id" />
} @placeholder {
<section aria-label="Comments">
<h2>Comments</h2>
<p>Loading comments...</p>
</section>
}Zoekmachines indexeren de placeholder-inhoud tijdens SSR. Een beschrijvende placeholder zorgt ervoor dat de pagina semantisch compleet blijft.
Incrementele hydratie met @defer
Angular 19 introduceerde incrementele hydratie als developer preview, en Angular 22 stabiliseert het als een productieklare functionaliteit. Incrementele hydratie breidt @defer uit met een hydrate-trigger die bepaalt wanneer een server-gerenderd component interactief wordt op de client.
@defer (hydrate on viewport) {
<product-gallery [images]="product.images" />
}
@defer (hydrate on interaction) {
<product-reviews [productId]="product.id" />
}In tegenstelling tot standaard @defer rendert incrementele hydratie de volledige HTML van het component op de server. De client ontvangt complete markup maar stelt de hydratie van het component uit tot de trigger wordt geactiveerd. Het resultaat: de browser schildert de volledige pagina onmiddellijk, maar de JavaScript-uitvoering wordt uitgesteld.
Het Angular-team rapporteert consistente verbeteringen van 40-50% in LCP-scores bij het gebruik van incrementele hydratie op content-intensieve pagina's. Angular DevTools in versie 22 visualiseert hydratie-statussen (pending, hydrated, error) rechtstreeks in de componentinspector.
Praktijkpatronen en performancestrategie
Patroon 1: zwaar dashboard met meerdere uitgestelde panelen
<div class="grid grid-cols-2 gap-4">
@defer (on viewport; prefetch on idle) {
<sales-chart />
} @placeholder {
<skeleton-card height="300px" />
}
@defer (on viewport; prefetch on idle) {
<user-activity-feed />
} @placeholder {
<skeleton-card height="300px" />
}
@defer (on interaction) {
<export-panel />
} @placeholder {
<button>Export data</button>
}
</div>Elk paneel wordt onafhankelijk geladen. Het exportpaneel blijft ongeladen totdat de gebruiker het expliciet opvraagt, waardoor een volledige chunkdownload wordt bespaard voor gebruikers die nooit exporteren.
Patroon 2: conditioneel laden van functionaliteit met signals
export class EditorComponent {
user = inject(UserService).currentUser;
isPremium = computed(() => this.user()?.plan === 'premium');
}
// editor.component.html
@defer (when isPremium()) {
<ai-assistant />
} @placeholder {
<upgrade-banner />
}Gebruikers met het gratis abonnement downloaden nooit de AI-assistentchunk. De upgrade-banner fungeert zowel als placeholder als conversieprompt.
Veelvoorkomende valkuilen vermijden
Het nesten van @defer-blokken met dezelfde trigger veroorzaakt gelijktijdige chunkdownloads. Spreid triggers over geneste blokken:
// Avoid: both fire on idle simultaneously
@defer {
@defer {
<nested-heavy-component />
}
}
// Better: outer on idle, inner on viewport
@defer (on idle) {
<wrapper-component />
}
// Inside wrapper-component template:
@defer (on viewport) {
<nested-heavy-component />
}Een andere valkuil: het gebruik van @defer voor componenten die zich al in het kritieke renderpad bevinden. Het uitstellen van boven-de-vouw-content verhoogt de LCP omdat de browser de chunk eerst moet downloaden en uitvoeren voordat het scherm wordt geschilderd. Reserveer @defer voor content onder de vouw of door gebruikers geactiveerde content.
@defer versus routergebaseerd lazy loading
Routergebaseerd lazy loading en @defer vullen elkaar aan. Routergebaseerd lazy loading splitst op routeniveau, waarbij volledige feature-modules worden uitgesteld. @defer splitst binnen een template, waarbij individuele componenten worden uitgesteld.
| Aspect | Router Lazy Loading | @defer |
|--------|-------------------|--------|
| Granulariteit | Route-niveau | Component-niveau |
| Trigger | Navigatie-event | viewport, idle, interaction, hover, timer, conditie |
| SSR-gedrag | Volledige server-rendering | Placeholder op de server |
| Standalone vereist | Nee (werkt met NgModules) | Ja (alleen standalone) |
| Prefetching | preloadingStrategy | prefetch on-clausule |
| Toepassing | Feature-modules, pagina's | Widgets, panelen, conditionele UI |
Een typische applicatie maakt gebruik van beide benaderingen: routergebaseerd lazy loading voor feature-gebieden op het hoogste niveau en @defer voor zware componenten binnen die gebieden.
Sollicitatievragen over Angular @defer
Technische sollicitatiegesprekken behandelen steeds vaker @defer omdat het centraal staat in de performancestrategie van Angular. Hieronder volgen patronen die regelmatig voorkomen in Angular-sollicitatievragen.
Vraag: Wat gebeurt er als een niet-standalone component in @defer wordt geplaatst?
Het component wordt ongeacht het @defer-blok eager geladen. De Angular-compiler kan componenten die in een NgModule zijn gedeclareerd niet in afzonderlijke chunks extraheren. Er wordt geen foutmelding gegenereerd, maar de optimalisatie faalt stilzwijgend.
Vraag: Hoe gedraagt @defer zich tijdens SSR?
De server rendert de @placeholder-inhoud. Het uitgestelde component wordt nooit server-side gerenderd. Hydratie vindt plaats op de client wanneer de trigger wordt geactiveerd (of via hydrate on voor incrementele hydratie).
Vraag: Kan @defer worden gebruikt met OnPush change detection?
Ja. @defer is een functionaliteit op templateniveau en werkt met elke change-detectiestrategie. Het uitgestelde component volgt na het laden zijn eigen change-detectieconfiguratie.
Vraag: Wat is het verschil tussen on idle en on immediate?
on idle wacht tot de browser al het lopende werk heeft afgerond via requestIdleCallback. on immediate triggert direct nadat Angular de initiele rendercyclus heeft voltooid, zonder te wachten op een inactieve status. on immediate is nuttig voor componenten die snel moeten laden maar de eerste paint niet mogen blokkeren.
Voor een breder scala aan Angular-sollicitatievoorbereiding, zie de module Angular change detection en de module Angular signals.
Begin met oefenen!
Test je kennis met onze gespreksimulatoren en technische tests.
Conclusie
@defersplitst standalone componenten af in afzonderlijke chunks die on-demand worden geladen, waardoor de initiele bundelgrootte wordt verkleind zonder routeherstructurering- Zeven triggertypes (
idle,viewport,interaction,hover,timer,immediate,when) dekken elke laadstrategie van passief tot gebruikersgestuurd prefetch onontkoppelt het downloaden van chunks van het renderen van componenten, waardoor waargenomen vertraging bij door gebruikers geactiveerde componenten wordt geelimineerd- Incrementele hydratie (
hydrate on) rendert volledige HTML op de server terwijl JavaScript-uitvoering naar de client wordt uitgesteld, met 40-50% verbetering in LCP op content-intensieve pagina's @placeholder-inhoud wordt gerenderd tijdens SSR en moet semantisch betekenisvol zijn voor SEO@defervult routergebaseerd lazy loading aan: routes voor splitsing op functieniveau,@defervoor splitsing op componentniveau binnen templates- Niet-standalone componenten kunnen niet worden uitgesteld en worden stilzwijgend eager geladen
Begin met oefenen!
Test je kennis met onze gespreksimulatoren en technische tests.
Tags
Delen
Gerelateerde artikelen

Angular 19 sollicitatievragen: Signals, SSR en onmisbare concepten
De meest voorkomende Angular 19 sollicitatievragen: Signals, incrementele hydration, zoneless change detection en nieuwe reactieve API's met codevoorbeelden en verwachte antwoorden.

Angular 19 Zoneless: Performance en Change Detection zonder Zone.js
Technische gids over Zoneless Change Detection in Angular 19 en 20. Werking van Signal-gebaseerde reactiviteit, activering van provideZonelessChangeDetection, migratieproblemen met setTimeout en Reactive Forms, SSR zonder Zone.js en prestatiebenchmarks.

Angular 20 in 2026: Resource API, httpResource en sollicitatievragen
Angular 20 introduceert de Resource API en httpResource als signal-gebaseerde alternatieven voor handmatige HttpClient-subscriptions. Deze handleiding behandelt alle drie Resource-varianten, Zod-validatie en veelgestelde sollicitatievragen.