Caricamento lento di immagini ed elementi <iframe>

Le immagini e gli elementi <iframe> spesso consumano più larghezza di banda rispetto ad altri tipi di risorse. Nel caso degli elementi <iframe>, il caricamento e il rendering delle pagine al loro interno possono richiedere un tempo di elaborazione aggiuntivo.

Nel caso del caricamento differito delle immagini, posticipare il caricamento delle immagini al di fuori dell'area visibile iniziale può essere utile per ridurre la contesa della larghezza di banda per le risorse più critiche all'interno dell'area visibile iniziale. In alcuni casi, in cui le connessioni di rete sono scarse, questo può migliorare il Largest Contentful Paint (LCP) di una pagina e la larghezza di banda riallocata può contribuire a caricare e visualizzare più velocemente gli elementi candidati LCP.

Per quanto riguarda gli elementi <iframe>, l'Interaction to Next Paint (INP) di una pagina può essere migliorata durante l'avvio tramite il caricamento differito. Questo perché un <iframe> è un documento HTML completamente separato con le proprie risorse secondarie. Sebbene gli elementi <iframe> possano essere eseguiti in un processo separato, non è raro che condividano un processo con altri thread, il che può creare condizioni in cui le pagine diventano meno sensibili all'input dell'utente.

Pertanto, posticipare il caricamento di immagini e elementi <iframe> off-screen è una tecnica che vale la pena perseguire e richiede uno sforzo relativamente ridotto per un ritorno ragionevolmente buono in termini di prestazioni. Questo modulo spiega come eseguire il caricamento differito di questi due tipi di elementi per un'esperienza utente più rapida e migliore durante il periodo di avvio critico della pagina.

Carica le immagini con il caricamento lento con l'attributo loading

L'attributo loading può essere aggiunto agli elementi <img> per indicare ai browser come devono essere caricati:

  • "eager" comunica al browser che l'immagine deve essere caricata immediatamente, anche se non è visibile nel viewport iniziale. Questo è anche il valore predefinito per l'attributo loading.
  • "lazy" posticipa il caricamento di un'immagine finché non si trova a una distanza impostata dall'area visibile. Questa distanza varia in base al browser, ma spesso viene impostata su un valore sufficientemente elevato da consentire il caricamento dell'immagine entro il momento in cui l'utente arriva a quella posizione.

Vale anche la pena notare che, se utilizzi l'elemento <picture>, l'attributo loading deve essere comunque applicato all'elemento secondario <img>, non all'elemento <picture> stesso. Questo accade perché l'elemento <picture> è un contenitore che contiene elementi <source> aggiuntivi che rimandano a diverse candidate per l'immagine e la candidata scelta dal browser viene applicata direttamente al suo elemento secondario <img>.

Non caricare le immagini con caricamento lento nell'area visibile iniziale

Devi aggiungere l'attributo loading="lazy" solo agli elementi <img> posizionati al di fuori dell'area visibile iniziale. Tuttavia, può essere complesso conoscere la posizione esatta di un elemento all'interno dell'area visibile prima del rendering della pagina. È necessario tenere conto di dimensioni, proporzioni e dispositivi diversi dell'area visibile.

Ad esempio, l'area visibile di un computer può essere molto diversa da quella di un cellulare perché offre più spazio verticale, il che potrebbe consentire di adattare le immagini all'area visibile iniziale, diversamente da quanto avviene su un dispositivo fisicamente più piccolo. I tablet utilizzati in orientamento verticale mostrano anche una notevole quantità di spazio verticale, forse anche più di alcuni computer.

Tuttavia, in alcuni casi è abbastanza chiaro che devi evitare di applicare loading="lazy". Ad esempio, devi omettere l'attributo loading="lazy" dagli elementi <img> nel caso di immagini hero o di altri casi d'uso delle immagini in cui è probabile che gli elementi <img> vengano visualizzati sopra il ribaltamento o nella parte superiore del layout su qualsiasi dispositivo. Questo è ancora più importante per le immagini che potrebbero essere candidate a LCP.

Le immagini con caricamento differito devono attendere che il browser completa il layout per sapere se la posizione finale dell'immagine è all'interno dell'area visibile. Ciò significa che se un elemento <img> nel viewport visibile ha un attributo loading="lazy", viene richiesto solo dopo il download, l'analisi e l'applicazione di tutto il CSS alla pagina, anziché essere recuperato non appena viene rilevato dall'Scanner di precaricamento nel markup non elaborato.

Poiché l'attributo loading dell'elemento <img> è supportato su tutti i browser principali, non è necessario utilizzare JavaScript per il caricamento lento delle immagini, in quanto l'aggiunta di JavaScript aggiuntivo a una pagina per fornire funzionalità già fornite dal browser influisce su altri aspetti del rendimento della pagina, come l'INP.

Demo del caricamento lento delle immagini

Carica elementi <iframe> con caricamento lento

Il caricamento lento degli elementi <iframe> finché non sono visibili nel viewport può far risparmiare dati significativi e migliorare il caricamento delle risorse fondamentali necessarie per il caricamento della pagina di primo livello. Inoltre, poiché gli elementi <iframe> sono essenzialmente interi documenti HTML caricati all'interno di un documento di primo livello, possono includere un numero significativo di risorse secondarie, in particolare JavaScript, che possono influire notevolmente sull'INP di una pagina se le attività all'interno di questi frame richiedono un tempo di elaborazione significativo.

Gli elementi incorporati di terze parti sono un caso d'uso comune per gli elementi <iframe>. Ad esempio, i video player incorporati o i post sui social media utilizzano comunemente elementi <iframe> e spesso richiedono un numero significativo di risorse secondarie, il che può anche comportare una contesa della larghezza di banda per le risorse della pagina di primo livello. Ad esempio, il caricamento differito dell'embed di un video di YouTube consente di risparmiare più di 500 KiB durante il caricamento iniziale della pagina, mentre il caricamento differito del plug-in del pulsante Mi piace di Facebook consente di risparmiare più di 200 KiB, la maggior parte dei quali è JavaScript.

In ogni caso, ogni volta che in una pagina è presente un <iframe> below the fold, ti consigliamo vivamente di utilizzarlo con il caricamento lento se non è fondamentale caricarlo in primo piano, in quanto questo può migliorare notevolmente l'esperienza utente.

L'attributo loading per gli elementi <iframe>

L'attributo loading negli elementi <iframe> è supportato anche in tutti i browser principali. I valori dell'attributo loading e i relativi comportamenti sono gli stessi degli elementi <img> che utilizzano l'attributo loading:

  • "eager" è il valore predefinito. Indica al browser di caricare immediatamente il codice HTML dell'elemento <iframe> e le relative risorse secondarie.
  • "lazy" rimanda il caricamento del codice HTML dell'elemento <iframe> e delle relative risorse secondarie fino a quando non si trova a una distanza predefinita dall'area visibile.

Demo di iframe con caricamento lento

Facciate

Anziché caricare un'integrazione immediatamente durante il caricamento della pagina, puoi caricarla su richiesta in risposta a un'interazione dell'utente. Ciò può essere fatto mostrando un'immagine o un altro elemento HTML appropriato finché l'utente non interagisce con esso. Una volta che l'utente interagisce con l'elemento, puoi sostituirlo con l'embed di terze parti. Questa tecnica è nota come facciata.

Un caso d'uso comune per le facciate è l'inserimento di video di servizi di terze parti, dove l'inserimento può comportare il caricamento di molte risorse aggiuntive e potenzialmente costose, come JavaScript, oltre ai contenuti video stessi. In questi casi, a meno che non esista una necessità legittima di riprodurre automaticamente un video, i video incorporati richiedono all'utente di interagire con loro prima della riproduzione facendo clic sul pulsante di riproduzione.

Questa è un'occasione unica per mostrare un'immagine statica visivamente simile all'embed del video e risparmiare una notevole larghezza di banda. Quando l'utente fa clic sull'immagine, questa viene sostituita dall'embed <iframe> effettivo, che attiva il download dell'HTML dell'elemento <iframe> di terze parti e delle relative risorse secondarie.

Oltre a migliorare il caricamento iniziale della pagina, un altro vantaggio fondamentale è che, se l'utente non riproduce mai il video, le risorse necessarie per la sua visualizzazione non vengono mai scaricate. Si tratta di un buon modello, in quanto garantisce che l'utente scarichi solo ciò che effettivamente vuole, senza fare supposizioni potenzialmente errate sulle sue esigenze.

I widget di chat sono un altro ottimo caso d'uso per la tecnica della facciata. La maggior parte dei widget di chat scarica quantità significative di JavaScript che possono influire negativamente sul caricamento delle pagine e sulla reattività all'input degli utenti. Come per il caricamento di qualsiasi elemento in anteprima, il costo viene addebitato al momento del caricamento, ma nel caso di un widget di chat non tutti gli utenti hanno intenzione di interagire con esso.

Con un facade, invece, è possibile sostituire il pulsante "Inizia chat" di terze parti con un pulsante falso. Una volta che l'utente interagisce in modo significativo con il widget, ad esempio passando il mouse sopra per un periodo di tempo ragionevole o facendo clic, il widget di chat effettivo e funzionale viene inserito quando l'utente ne ha bisogno.

Sebbene sia certamente possibile creare le tue proprie facciate, esistono opzioni open source disponibili per le terze parti più popolari, come lite-youtube-embed per i video di YouTube, lite-vimeo-embed per i video di Vimeo e React Live Chat loader per i widget di chat.

Librerie di caricamento differito JavaScript

Se devi eseguire il caricamento differito di elementi <video>, immagini poster degli elementi <video>, immagini caricate dalla proprietà CSS background-image o altri elementi non supportati, puoi farlo con una soluzione di caricamento differito basata su JavaScript, come lazysizes o yall.js, poiché il caricamento differito di questi tipi di risorse non è una funzionalità a livello di browser.

In particolare, la riproduzione automatica e il looping degli elementi <video> senza traccia audio sono un'alternativa molto più efficiente rispetto all'utilizzo di GIF animate, che spesso possono essere molto più grandi di una risorsa video di qualità visiva equivalente. Tuttavia, questi video possono comunque occupare una quantità significativa di larghezza di banda, perciò il caricamento differito è un'ottimizzazione aggiuntiva che può contribuire notevolmente a ridurre lo spreco di larghezza di banda.

La maggior parte di queste librerie utilizza l'API IntersectionObserver e, se il codice HTML di una pagina cambia dopo il caricamento iniziale, anche l'API MutationObserver per riconoscere quando un elemento entra nell'area visibile dell'utente. Se l'immagine è visibile o si sta avvicinando al viewport, la libreria JavaScript sostituisce l'attributo non standard (spesso data-src o un attributo simile) con l'attributo corretto, ad esempio src.

Supponiamo che tu abbia un video che sostituisce una GIF animata, ma che tu voglia caricarlo dinamicamente con una soluzione JavaScript. Questo è possibile con yall.js con il seguente pattern di markup:

<!-- The autoplay, loop, muted, and playsinline attributes are to
     ensure the video can autoplay without user intervention. -->
<video class="lazy" autoplay loop muted playsinline width="320" height="480">
  <source data-src="video.webm" type="video/webm">
  <source data-src="video.mp4" type="video/mp4">
</video>

Per impostazione predefinita, yall.js osserva tutti gli elementi HTML idonei con una classe di "lazy". Una volta caricato ed eseguito sulla pagina, il file yall.js non carica il video finché l'utente non lo fa scorrere nell'area visibile della pagina. A questo punto, gli attributi data-src degli elementi <source> secondari dell'elemento <video> vengono sostituiti con gli attributi src, che inviano una richiesta di download del video e avviano automaticamente la riproduzione.

Verifica le tue conoscenze

Qual è il valore predefinito dell'attributo loading per entrambi gli elementi <img> e <iframe>?

"eager"
Esatto!
"lazy"
Riprova.

Quando è ragionevole utilizzare soluzioni di caricamento differito basate su JavaScript?

Per qualsiasi risorsa che può essere caricata tramite caricamento lento.
Riprova.
Per le risorse in cui l'attributo loading non è supportato, ad esempio nel caso di video con riproduzione automatica destinati a sostituire le immagini animate o per il caricamento differito dell'immagine poster di un elemento <video>.
Esatto!

Quando una facciata è una tecnica utile?

Per qualsiasi incorporamento di terze parti che consuma dati significativi, indipendentemente dalle esigenze dell'utente.
Riprova.
Per qualsiasi incorporamento di terze parti in cui le risorse necessarie per il caricamento non sono solo sostanziali, ma esiste una probabilità significativa che non tutti gli utenti possano interagire con esse.
Esatto!

A seguire: Precaricamento e prerendering

Ora che hai capito come funziona il caricamento differito delle immagini e degli elementi <iframe>, puoi assicurarti che le pagine possano caricarsi più velocemente, rispettando al contempo le esigenze dei tuoi utenti. Tuttavia, in alcuni casi può essere auspicabile un caricamento speculativo delle risorse. Nel modulo successivo, scopri di più sul pre-caricamento e sul pre-rendering e su come queste tecniche, se utilizzate con attenzione, possono accelerare notevolmente la navigazione alle pagine successive caricandole in anticipo.