# Angular @defer nel 2026: Lazy Loading Dichiarativo e Domande da Colloquio Tecnico > Guida approfondita ai blocchi @defer di Angular: lazy loading dichiarativo con trigger viewport, interaction e timer. Prefetching, SSR, idratazione incrementale e domande da colloquio tecnico. - Published: 2026-06-14 - Updated: 2026-06-14 - Author: SharpSkill - Tags: angular, angular-defer, lazy-loading, performance, ssr, signals, deep-dive - Reading time: 9 min --- I blocchi `@defer` di Angular risolvono un problema che il lazy loading basato su router non ha mai potuto affrontare: il caricamento on-demand di singoli componenti, direttive e pipe senza la necessità di ristrutturare l'applicazione in route separate. Introdotti in Angular 17 e stabilizzati nel corso delle versioni successive fino ad Angular 22, i blocchi `@defer` trasformano quello che in precedenza richiedeva import dinamici, flag `*ngIf` e configurazioni webpack in un singolo costrutto dichiarativo a livello di template. > **Che cosa fa @defer** > > `@defer` istruisce il compilatore Angular a separare i componenti racchiusi nel blocco in chunk JavaScript distinti, caricati soltanto quando una condizione trigger si attiva. Il browser scarica meno JavaScript inizialmente, migliorando il Largest Contentful Paint (LCP) e il Time to First Byte (TTFB) senza configurazioni manuali di code-splitting. ## Come funziona @defer internamente Quando il compilatore Angular incontra un blocco `@defer`, estrae ogni componente standalone, direttiva e pipe al suo interno in un chunk separato. Il bundle principale viene distribuito senza queste dipendenze. A runtime, Angular valuta la condizione trigger ed effettua il fetch del chunk tramite una chiamata dinamica `import()`. Il blocco supporta quattro sotto-blocchi che controllano ciò che l'utente visualizza durante il ciclo di vita del caricamento: ```typescript // app.component.html @defer (on viewport) { } @placeholder {
} @loading (minimum 200ms) { } @error {

Failed to load the dashboard. Please refresh.

} ``` `@placeholder` viene renderizzato prima che il trigger si attivi. `@loading` appare durante il download del chunk, con un parametro opzionale `minimum` per prevenire il flickering. `@error` intercetta errori di rete o errori di caricamento del chunk. Il parametro `minimum` su `@loading` evita un flash dello spinner quando il chunk viene caricato rapidamente dalla cache. Un vincolo fondamentale: ogni dipendenza all'interno di `@defer` deve essere standalone. I componenti non-standalone dichiarati in un `NgModule` non possono essere differiti e vengono caricati eagerly indipendentemente dal wrapper `@defer`. ## Tipi di trigger: controllare quando i componenti vengono caricati Angular fornisce sette trigger integrati, ciascuno orientato a una diversa strategia di caricamento. Più trigger possono essere combinati con il punto e virgola e vengono valutati come condizioni OR. ```typescript // product-page.component.html // Loads when the browser goes idle (default) @defer { } // Loads when the element enters the viewport @defer (on viewport) { } // Loads on click or keydown @defer (on interaction) { } @placeholder { } // Loads on mouseenter or focusin @defer (on hover) { } // Loads after 3 seconds @defer (on timer(3s)) { } // Loads immediately after initial render @defer (on immediate) { } ``` Il trigger `on viewport` utilizza internamente l'[Intersection Observer API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API). Il trigger `on idle` delega a `requestIdleCallback`, risultando il default più sicuro per contenuti below-the-fold. Il trigger `on timer` accetta durate in millisecondi (`500ms`) o secondi (`3s`). ### Il trigger `when` per condizioni reattive Oltre ai trigger basati su eventi, `when` accetta qualsiasi espressione booleana, incluse le letture di signal: ```typescript // dashboard.component.ts export class DashboardComponent { showAdvanced = signal(false); } // dashboard.component.html @defer (when showAdvanced()) { } @placeholder { } ``` Combinare `on` e `when` è perfettamente valido. Angular li tratta come condizioni OR: il blocco viene caricato quando una delle due condizioni si verifica. ## Prefetching: separare il download dalla visualizzazione Il prefetching disaccoppia il momento del download del chunk dal momento in cui il componente viene renderizzato. Questo elimina la latenza percepita scaricando il JavaScript prima che l'utente attivi il trigger. ```typescript // settings.component.html @defer (on interaction; prefetch on idle) { } @placeholder { } ``` In questo pattern, il browser scarica il chunk di `account-settings` durante i momenti di inattività. Quando l'utente clicca, il componente viene renderizzato istantaneamente perché il codice è già disponibile. Il prefetching accetta gli stessi tipi di trigger della clausola principale `on`. Un pattern comune per le dashboard: eseguire il prefetch di componenti pesanti durante l'idle e differire il rendering all'ingresso nel viewport. ```typescript // analytics.component.html @defer (on viewport; prefetch on idle) { } @placeholder (minimum 100ms) {
} ``` Il parametro `minimum` su `@placeholder` previene un flash di layout quando l'utente scorre rapidamente e il componente differito viene caricato quasi istantaneamente. ## @defer e Server-Side Rendering Sul server, i blocchi `@defer` renderizzano il contenuto di `@placeholder` per impostazione predefinita. Il componente differito non viene mai renderizzato lato server. Questo comportamento è intenzionale: il download del chunk ha senso esclusivamente in un contesto browser. Per i contenuti critici ai fini della SEO, ciò significa che il `@placeholder` deve contenere HTML semanticamente significativo, non soltanto uno spinner: ```typescript // blog-post.component.html @defer (on viewport) { } @placeholder {

Comments

Loading comments...

} ``` I motori di ricerca indicizzano il contenuto del placeholder durante il rendering SSR. Un placeholder descrittivo garantisce che la pagina rimanga semanticamente completa. ## Idratazione incrementale con @defer Angular 19 ha introdotto l'[idratazione incrementale](https://angular.dev/guide/incremental-hydration) in developer preview, e Angular 22 la stabilizza come funzionalità pronta per la produzione. L'idratazione incrementale estende `@defer` con un trigger `hydrate` che controlla quando un componente renderizzato lato server diventa interattivo sul client. ```typescript // product-page.component.html @defer (hydrate on viewport) { } @defer (hydrate on interaction) { } ``` A differenza del `@defer` standard, l'idratazione incrementale renderizza l'HTML completo del componente sul server. Il client riceve il markup completo ma posticipa l'idratazione del componente fino all'attivazione del trigger. Il risultato: il browser visualizza la pagina completa immediatamente, ma l'esecuzione del JavaScript viene differita. Il team Angular riporta miglioramenti costanti del 40-50% nei punteggi LCP quando si utilizza l'idratazione incrementale su pagine ricche di contenuti. Angular DevTools nella versione 22 visualizza gli stati di idratazione (pending, hydrated, error) direttamente nell'inspector dei componenti. ## Pattern reali e strategia di ottimizzazione delle performance ### Pattern 1: Dashboard pesante con pannelli differiti multipli ```typescript // dashboard.component.html
@defer (on viewport; prefetch on idle) { } @placeholder { } @defer (on viewport; prefetch on idle) { } @placeholder { } @defer (on interaction) { } @placeholder { }
``` Ogni pannello viene caricato in modo indipendente. Il pannello di esportazione rimane scaricato fino a quando l'utente non lo richiede esplicitamente, risparmiando il download di un intero chunk per gli utenti che non esportano mai dati. ### Pattern 2: Caricamento condizionale di funzionalità con signal ```typescript // editor.component.ts export class EditorComponent { user = inject(UserService).currentUser; isPremium = computed(() => this.user()?.plan === 'premium'); } // editor.component.html @defer (when isPremium()) { } @placeholder { } ``` Gli utenti del piano gratuito non scaricano mai il chunk dell'assistente AI. Il banner di upgrade funge sia da placeholder che da elemento di conversione. ### Evitare le insidie più comuni Annidare blocchi `@defer` con lo stesso trigger causa download simultanei dei chunk. I trigger devono essere sfalsati tra blocchi annidati: ```typescript // Avoid: both fire on idle simultaneously @defer { @defer { } } // Better: outer on idle, inner on viewport @defer (on idle) { } // Inside wrapper-component template: @defer (on viewport) { } ``` Un'altra insidia frequente: utilizzare `@defer` per componenti che si trovano già nel percorso critico di rendering. Differire contenuti above-the-fold aumenta l'LCP perché il browser deve scaricare ed eseguire il chunk prima di poter dipingere la pagina. Il consiglio è riservare `@defer` per contenuti below-the-fold o attivati dall'utente. ## @defer vs Lazy Loading basato su Router Il lazy loading basato su router e `@defer` sono strumenti complementari. Il lazy loading del router suddivide a livello di route, differendo interi feature module. `@defer` suddivide all'interno di un template, differendo singoli componenti. | Aspetto | Router Lazy Loading | @defer | |---------|-------------------|--------| | Granularità | Livello di route | Livello di componente | | Trigger | Evento di navigazione | viewport, idle, interaction, hover, timer, condizione | | Comportamento SSR | Rendering server completo | Placeholder sul server | | Richiede standalone | No (funziona con NgModules) | Sì (solo standalone) | | Prefetching | `preloadingStrategy` | clausola `prefetch on` | | Caso d'uso | Feature module, pagine | Widget, pannelli, UI condizionale | Un'applicazione tipica utilizza entrambi gli approcci: il lazy loading del router per le aree funzionali di primo livello e `@defer` per i componenti pesanti all'interno di quelle aree. ## Domande da colloquio tecnico su Angular @defer I colloqui tecnici includono sempre più frequentemente domande su `@defer`, dato il suo ruolo centrale nella strategia di ottimizzazione delle performance Angular. Di seguito i pattern che compaiono regolarmente nelle [domande di colloquio Angular](/technologies/angular/interview-questions/standalone-components). **D: Che cosa succede se un componente non-standalone viene inserito all'interno di @defer?** Il componente viene caricato eagerly indipendentemente dal blocco `@defer`. Il compilatore Angular non può estrarre componenti dichiarati in un NgModule in chunk separati. Non viene generato alcun errore, ma l'ottimizzazione fallisce silenziosamente. **D: Come si comporta @defer durante il Server-Side Rendering?** Il server renderizza il contenuto di `@placeholder`. Il componente differito non viene mai renderizzato lato server. L'idratazione avviene sul client quando il trigger si attiva (oppure tramite `hydrate on` per l'idratazione incrementale). **D: È possibile utilizzare @defer con la strategia di change detection OnPush?** Sì. `@defer` è una funzionalità a livello di template e funziona con qualsiasi strategia di change detection. Il componente differito segue la propria configurazione di change detection una volta caricato. Per un approfondimento sul change detection, consultare il modulo dedicato su [Angular change detection](/technologies/angular/interview-questions/change-detection). **D: Qual è la differenza tra `on idle` e `on immediate`?** `on idle` attende che il browser completi tutto il lavoro pendente tramite `requestIdleCallback`. `on immediate` si attiva subito dopo il completamento del render iniziale da parte di Angular, senza attendere lo stato di idle. `on immediate` risulta utile per componenti che devono essere caricati presto ma senza bloccare il first paint. **D: Come interagiscono `on` e `when` quando vengono combinati in un singolo blocco @defer?** Angular li tratta come condizioni OR. Il blocco viene caricato quando una qualsiasi delle condizioni specificate si verifica per prima. Questo consente pattern flessibili dove un componente può essere caricato sia in risposta a un evento del browser che a un cambiamento di stato nell'applicazione. **D: Come si può garantire che il contenuto differito non impatti negativamente sulla SEO?** Durante il rendering SSR, il server restituisce esclusivamente il contenuto di `@placeholder`. Per contenuti rilevanti ai fini SEO, il placeholder deve contenere HTML semanticamente significativo che i motori di ricerca possano indicizzare. Utilizzare tag semantici come `
`, `

` e testo descrittivo nel placeholder garantisce la completezza semantica della pagina. Per una preparazione completa ai colloqui Angular, consultare anche il modulo sugli [Angular signals](/technologies/angular/interview-questions/angular-signals) e quello sul [change detection](/technologies/angular/interview-questions/change-detection). ## Conclusione - `@defer` separa i componenti standalone in chunk distinti caricati on-demand, riducendo la dimensione del bundle iniziale senza ristrutturazione delle route - Sette tipi di trigger (`idle`, `viewport`, `interaction`, `hover`, `timer`, `immediate`, `when`) coprono ogni strategia di caricamento, da quella passiva a quella guidata dall'utente - `prefetch on` disaccoppia il download del chunk dal rendering del componente, eliminando la latenza percepita sui componenti attivati dall'utente - L'idratazione incrementale (`hydrate on`) renderizza l'HTML completo sul server posticipando l'esecuzione JavaScript al client, con miglioramenti del 40-50% nei punteggi LCP su pagine ricche di contenuti - Il contenuto di `@placeholder` viene renderizzato durante l'SSR e deve essere semanticamente significativo ai fini della SEO - `@defer` complementa il lazy loading basato su router: le route per la suddivisione a livello di feature, `@defer` per la suddivisione a livello di componente all'interno dei template - I componenti non-standalone non possono essere differiti e vengono caricati eagerly in modo silenzioso --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/it/blog/angular/angular-defer-loading-declarative-lazy-loading-guide