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 di immagini con caricamento differito, posticipare il caricamento delle immagini che si trovano al di fuori della finestra iniziale può essere utile per ridurre la contesa della larghezza di banda per le risorse più importanti all'interno della finestra iniziale. In alcuni casi in cui le connessioni di rete sono scarse, ciò può migliorare la metrica Largest Contentful Paint (LCP) di una pagina e la larghezza di banda riassegnata può aiutare i candidati LCP a caricarsi e a eseguire il rendering più rapidamente.

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 reattive all'input dell'utente.

Pertanto, posticipare il caricamento delle immagini fuori schermo e degli elementi <iframe> è una tecnica da perseguire e richiede uno sforzo relativamente basso per un ritorno ragionevolmente buono in termini di prestazioni. Questo modulo spiega come caricare in modalità differita questi due tipi di elementi per un'esperienza utente più rapida e migliore durante il periodo di avvio critico della pagina.

Immagini con caricamento lento con l'attributo loading

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

  • "eager" indica al browser che l'immagine deve essere caricata immediatamente, anche se si trova al di fuori della finestra iniziale. Questo è anche il valore predefinito per l'attributo loading.
  • "lazy" posticipa il caricamento di un'immagine finché non si trova a una distanza prestabilita dall'area visibile. Questa distanza varia in base al browser, ma spesso è impostata in modo che l'immagine venga caricata quando l'utente scorre fino a visualizzarla.

È anche importante notare che se utilizzi l'elemento <picture>, l'attributo loading deve comunque essere applicato al relativo elemento secondario <img>, non all'elemento <picture> stesso. Questo perché l'elemento <picture> è un contenitore che contiene altri elementi <source> che puntano a diversi candidati immagine e il candidato scelto dal browser viene applicato direttamente all'elemento secondario <img>.

Non caricare lentamente le immagini che si trovano 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 difficile conoscere la posizione esatta di un elemento rispetto all'area visibile prima del rendering della pagina. Devono essere prese in considerazione diverse dimensioni dell'area visibile, proporzioni e dispositivi.

Ad esempio, l'area visibile di un computer può essere molto diversa da quella di un cellulare, in quanto offre più spazio verticale, in cui è possibile inserire immagini nell'area visibile iniziale che non apparirebbero nell'area visibile iniziale di un dispositivo fisicamente più piccolo. I tablet utilizzati in orientamento verticale mostrano anche una notevole quantità di spazio verticale, forse anche più di alcuni dispositivi desktop.

Tuttavia, in alcuni casi è abbastanza chiaro che devi evitare di applicare loading="lazy". Ad esempio, devi assolutamente omettere l'attributo loading="lazy" dagli elementi <img> nei casi di immagini hero o altri casi d'uso delle immagini in cui è probabile che gli elementi <img> vengano visualizzati sopra la piega o vicino alla parte superiore del layout su qualsiasi dispositivo. Questo è ancora più importante per le immagini che hanno maggiori probabilità di essere candidate LCP.

Le immagini con caricamento differito devono attendere che il browser termini il layout per sapere se la posizione finale dell'immagine si trova all'interno della finestra. Ciò significa che se un elemento <img> nel viewport visibile ha un attributo loading="lazy", viene richiesto solo dopo che tutto il CSS è stato scaricato, analizzato e applicato alla pagina, anziché essere recuperato non appena viene rilevato dallo scanner di precaricamento nel markup non elaborato.

Poiché l'attributo loading dell'elemento <img> è supportato da tutti i principali browser, non è necessario utilizzare JavaScript per il caricamento differito 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, ad esempio INP.

Demo del caricamento lento delle immagini

Caricamento lento di <iframe> elementi

Il caricamento differito degli elementi <iframe> fino a quando non sono visibili nella finestra può consentire di risparmiare una quantità significativa di dati e migliorare il caricamento delle risorse critiche 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 tempi di elaborazione significativi.

Gli incorporamenti 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 che possono anche causare contesa di larghezza di banda per le risorse della pagina di primo livello. Ad esempio, il caricamento differito dell'incorporamento 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, quando hai un <iframe> below the fold su una pagina, dovresti valutare seriamente di caricarlo in modo differito se non è fondamentale caricarlo subito, in quanto in questo modo puoi migliorare significativamente l'esperienza utente.

L'attributo loading per gli elementi <iframe>

L'attributo loading negli elementi <iframe> è supportato anche in tutti i principali browser. 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 l'HTML dell'elemento <iframe> e le relative risorse secondarie.
  • "lazy" posticipa il caricamento del codice HTML dell'elemento <iframe> e delle relative risorse secondarie finché non si trova a una distanza predefinita dall'area visibile.

Demo di caricamento lento degli iframe

Facciate

Anziché caricare un incorporamento immediatamente durante il caricamento della pagina, puoi caricarlo 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'incorporamento di terze parti. Questa tecnica è nota come facciata.

Un caso d'uso comune per le facciate sono gli incorporamenti di video da servizi di terze parti in cui l'incorporamento può comportare il caricamento di molte risorse secondarie aggiuntive e potenzialmente costose, come JavaScript, oltre ai contenuti video stessi. In questo caso, a meno che non vi sia una necessità legittima di riprodurre automaticamente un video, gli incorporamenti video richiedono l'interazione dell'utente prima della riproduzione facendo clic sul pulsante di riproduzione.

Questa è un'ottima opportunità per mostrare un'immagine statica visivamente simile al video incorporato e risparmiare una notevole quantità di larghezza di banda. Quando l'utente fa clic sull'immagine, questa viene sostituita dall'incorporamento <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 riproduzione non vengono mai scaricate. Questo è un buon pattern, in quanto garantisce che l'utente scarichi solo ciò che effettivamente desidera, senza fare ipotesi possibilmente errate sulle esigenze dell'utente.

I widget di chat sono un altro ottimo caso d'uso per la tecnica della facciata. La maggior parte dei widget di chat scarica grandi quantità di JavaScript che possono influire negativamente sul caricamento della pagina e sulla reattività all'input utente. Come per il caricamento di qualsiasi elemento iniziale, il costo viene sostenuto al momento del caricamento, ma nel caso di un widget di chat, non tutti gli utenti non intendono mai interagire con esso.

Con un facade, invece, è possibile sostituire il pulsante "Avvia chat" di terze parti con un pulsante fittizio. Una volta che l'utente interagisce in modo significativo con il widget, ad esempio tenendo un puntatore sopra di esso per un periodo di tempo ragionevole o con un clic, il widget di chat funzionale effettivo viene inserito in posizione quando l'utente ne ha bisogno.

Sebbene sia certamente possibile creare le proprie facciate, sono disponibili opzioni open source per 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 JavaScript per il caricamento differito

Se devi caricare in differita gli elementi <video>, le immagini degli elementi <video>, le immagini poster 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 in loop degli elementi <video> senza traccia audio sono un'alternativa molto più efficiente rispetto all'utilizzo di GIF animate, che possono spesso essere diverse volte più grandi di una risorsa video di qualità visiva equivalente. Tuttavia, questi video possono comunque essere significativi in termini di larghezza di banda, pertanto il caricamento differito è un'ulteriore ottimizzazione che può contribuire notevolmente a ridurre la larghezza di banda sprecata.

La maggior parte di queste librerie funziona utilizzando l'API Intersection Observer e, inoltre, l'API Mutation Observer se l'HTML di una pagina cambia dopo il caricamento iniziale, per riconoscere quando un elemento entra nel riquadro visibile dell'utente. Se l'immagine è visibile o si sta avvicinando alla visualizzazione, 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 vuoi caricarlo in modalità differita con una soluzione JavaScript. È 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 yall.js sulla pagina, il video non viene caricato finché l'utente non lo scorre nell'area visibile. A questo punto, gli attributi data-src degli elementi secondari <source> dell'elemento <video> vengono sostituiti con gli attributi src, che inviano una richiesta per scaricare il video e avviare automaticamente la riproduzione.

Verifica le tue conoscenze

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

"lazy"
"eager"

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

Per le risorse in cui l'attributo loading non è supportato, ad esempio nel caso di video con riproduzione automatica destinati a sostituire immagini animate o a caricare in modalità differita l'immagine poster di un elemento <video>.
Per qualsiasi risorsa che può essere caricata in modo differito.

Quando una facciata è una tecnica utile?

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

A seguire: precaricamento e prerendering

Ora che hai una buona conoscenza del caricamento differito delle immagini e degli elementi <iframe>, sei in una buona posizione per garantire che le pagine possano essere caricate più rapidamente rispettando le esigenze dei tuoi utenti. Tuttavia, in alcuni casi il caricamento speculativo delle risorse può essere auspicabile. Nel modulo successivo, scopri di più sul prefetching e sul prerendering e su come queste tecniche, se utilizzate con attenzione, possono velocizzare notevolmente la navigazione nelle pagine successive caricandole in anticipo.