Angular: La Guida Definitiva al Lazy Loading con @defer

Sei pronto a rivoluzionare le performance della tua applicazione Angular? Con l’introduzione del blocco @defer
, il lazy loading dei componenti non è mai stato così semplice e potente. Dimentica complesse configurazioni di routing o import()
dinamici: oggi ti guiderò in un tutorial pratico per padroneggiare questa nuova, incredibile funzionalità.
Cos’è il Lazy Loading e Perché è Fondamentale?
Immagina di entrare in un enorme centro commerciale solo per comprare un caffè. Dovresti davvero caricare l’intera mappa del centro, con tutti i negozi e i servizi, solo per trovare il bar? Assolutamente no. Il lazy loading (o caricamento differito) applica la stessa logica alle web app: carica solo le risorse strettamente necessarie per la visualizzazione iniziale e rimanda il caricamento di tutto il resto a quando servirà davvero.
I vantaggi sono enormi:
- Initial Load più Veloce: Il primo caricamento della pagina è fulmineo, migliorando drasticamente l’esperienza utente (UX).
- Miglioramento dei Core Web Vitals: Un
Largest Contentful Paint
(LCP) più basso ti farà amare da Google. - Riduzione del Consumo di Risorse: Meno JavaScript da scaricare, analizzare ed eseguire significa un’app più leggera e reattiva.
Ecco a Voi @defer
: Il Nuovo Supereroe di Angular
Introdotto in Angular v17, il blocco @defer
è una sintassi per template che permette di dichiarare porzioni di UI da caricare in modo differito. La sua bellezza sta nella sua semplicità e potenza dichiarativa.
La sintassi base è incredibilmente intuitiva:
<p>Contenuto visibile subito.</p>
@defer {
<app-heavy-component />
<app-another-component />
}
In questo esempio, app-heavy-component
e app-another-component
(e tutte le loro dipendenze) non verranno inclusi nel bundle JavaScript iniziale. Verranno scaricati dal browser solo quando Angular lo riterrà opportuno. Ma quando, esattamente? È qui che la magia si scatena.
Trigger di @defer
: Quando Caricare i Componenti?
Il vero potere di @defer
risiede nella sua capacità di definire condizioni precise per avviare il caricamento. Vediamo i trigger principali.
1. on viewport
– Carica Quando Diventa Visibile
Questo è il caso d’uso più comune. Il componente viene caricato non appena il suo segnaposto entra nell’area visibile dello schermo (il viewport).
@defer (on viewport) {
<app-user-comments />
} @placeholder {
<div class="comments-skeleton"></div>
}
Caso d’uso: Perfetto per sezioni “in fondo alla pagina” come commenti, footer complessi o gallerie di immagini.
2. on interaction
– Carica all’Interazione dell’Utente
Il caricamento viene avviato quando l’utente clicca o interagisce con l’area del segnaposto.
@defer (on interaction) {
<app-contact-form />
} @placeholder {
<button>Carica il modulo di contatto</button>
}
Caso d’uso: Ideale per componenti interattivi come moduli, sezioni di chat o widget che non sono essenziali subito.
3. on hover
– Carica al Passaggio del Mouse
Il caricamento parte quando il cursore del mouse passa sopra l’area del segnaposto.
@defer (on hover) {
<app-mega-menu />
} @placeholder {
<div>Menu Avanzato</div>
}
Caso d’uso: Utile per menu complessi o anteprime che richiedono il caricamento di dati significativi.
4. when
– Il Trigger Condizionale
Puoi legare il caricamento a qualsiasi condizione booleana, come lo stato di un segnale o di una variabile.
// nel tuo component.ts
showCharts = signal(false);
<button (click)="showCharts.set(true)">Mostra Grafici</button>
@defer (when showCharts()) {
<app-dashboard-charts />
}
Caso d’uso: Dashboard, pannelli di amministrazione e qualsiasi UI che dipende da una specifica azione o stato dell’applicazione.
Gestire gli Stati: @placeholder
, @loading
, e @error
Un’esperienza utente di qualità richiede di gestire cosa l’utente vede mentre attende. @defer
offre blocchi specifici per questo.
@placeholder
: Obbligatorio. Mostra un contenuto temporaneo prima che il trigger si attivi. È fondamentale che sia leggerissimo. Puoi specificare anche un’altezza minima per evitare sgradevoli “salti” di layout (Layout Shift
).@loading
: Opzionale. Mostra un indicatore di caricamento (es. uno spinner) dopo che il trigger si è attivato e mentre il bundle del componente viene scaricato.@error
: Opzionale. Mostra un messaggio di errore se il caricamento del componente fallisce (es. per problemi di rete).
Ecco un esempio completo:
@defer (on viewport) {
<app-photo-gallery />
} @placeholder (minimum 500px) {
<div class="gallery-skeleton"></div>
} @loading {
<mat-spinner></mat-spinner>
} @error {
<p>Impossibile caricare la galleria. Riprova più tardi.</p>
}
Best Practice e Consigli da Pro
- Scegli il Trigger Giusto: Non usare
on interaction
se il componente è essenziale per la navigazione. Usaon viewport
per contenuti “below the fold”. - Mantieni i Placeholder Leggeri: Il blocco
@placeholder
non deve contenere logica complessa o componenti pesanti. L’ideale è HTML e CSS puri per creare uno “scheletro” dell’interfaccia. - Evita il Layout Shift: Usa il parametro
minimum
nel@placeholder
(es.@placeholder (minimum 200px)
) per riservare lo spazio verticale che il componente reale occuperà, evitando che la pagina “salti” al suo caricamento. - Prefetching Strategico: Puoi “pre-caricare” le risorse in background usando
prefetch
. Ad esempio, puoi avviare il download quando l’utente passa il mouse, e poi renderizzare il componente solo al click.@defer (on interaction; prefetch on hover) { <app-checkout-form /> }
- Non Abusarne: Non tutto deve essere caricato in modo differito. Componenti critici e immediatamente visibili (come l’header principale) dovrebbero essere caricati normalmente.
Per altre best practice su Angular: Top 8 estensioni di Visual Studio Code per Angular.
Pro e Contro di @defer
Vantaggi (Pro) 👍 | Svantaggi (Contro) 👎 |
---|---|
Semplicità Estrema: Sintassi dichiarativa e facile da capire. | Nuova Sintassi: Richiede un po’ di abitudine per chi arriva da *ngIf . |
Migliori Performance: Riduce drasticamente il TTI e migliora i Core Web Vitals. | Potenziale Layout Shift: Se non gestito correttamente con i placeholder. |
Controllo Granulare: I trigger offrono un controllo preciso sul quando e come caricare. | Over-engineering: Usarlo per componenti piccolissimi potrebbe essere eccessivo. |
Migliore UX: Con @loading e @error puoi gestire ogni stato del caricamento. | Non è una soluzione magica per un’architettura dati lenta. |
Conclusione: @defer
è il Futuro
Il blocco @defer
non è solo una nuova feature, è un cambio di paradigma per lo sviluppo di applicazioni Angular performanti. Rende il lazy loading accessibile, intuitivo e potente. Integrarlo nelle tue applicazioni significa offrire agli utenti un’esperienza più veloce e fluida, con un impatto positivo diretto sulla SEO e sulla soddisfazione generale.
Inizia a sperimentare oggi stesso: identifica i componenti più pesanti e meno critici della tua app e prova a caricarli con @defer
. I risultati ti sorprenderanno!
Hai già scoperto cosa sono e cosa si può fare con gli Angular Signals? No?! Allora corri subito a leggere il nostro articolo sll’argomento!