Ottimizzazione PageSpeed: migliorare i tempi di caricamento di un sito

La velocità di caricamento, chiamata anche PageSpeed, è un fattore di Ranking ufficiale. Le nuove misure incentrate sull’utente che compongono i Core Web Vitals sono diventate parte integrante di come vengono mostrati i risultati di ricerca con l’Update del Page Experience a metà del 2021. In questo articolo vedremo nello specifico cosa significa e in che modo la velocità di caricamento può essere migliorata.

In ogni caso, l’argomento del PageSpeed non è nulla di nuovo. Nel corso degli anni la velocità di caricamento è diventata sempre più rilevante per Google, che ha iniziato a prenderla in esame già nel dicembre del 2009 con il motto “Let’s make the web faster“, ponendo così le basi per il nuovo fattore di ranking.

I tempi di caricamento di un sito hanno da sempre avuto un influsso sugli User Signals: una pagina veloce ha infatti un effetto positivo sul bounce rate, siccome gli utenti saranno meno propensi ad abbandonarla e a selezionare un concorrente. Si tratta anche di un vantaggio per il click-through rate nelle SERP e sulla quantità di visualizzazioni della pagina, quindi potenzialmente anche per il conversion rate. Pertanto, il PageSpeed era già un fattore di ranking indiretto sin dall’utilizzo dei dati degli utenti e, negli ultimi anni, è diventato ufficialmente un fattore di ranking a tutti gli effetti.

Come posso ottimizzare i tempi di caricamento del mio sito e migliorare il PageSpeed?

Prima di tutto, esistono due fattori principali che influenzano i tempi di caricamento: la dimensione del sito (cioè i dati che devono essere trasmessi) e la latenza del server (il tempo che impiega il server, indipendentemente dalla trasmissione dei dati).

In generale, una quantità di dati maggiore e una larghezza di banda minore aumentano il tempo necessario per la trasmissione. Questo significa che l’obiettivo dell’ottimizzazione del PageSpeed deve essere quello di ridurre la quantità di dati da trasmettere, oppure la dimensione del sito.

Tuttavia, essendo i siti moderni formati da moltissimi tipi di file (HTML, CSS, JS, WebFonts, ecc.), la latenza, cioè la quantità di tempo che passa tra la richiesta e la risposta, ha a sua volta un’enorme influenza sul caricamento generale di un sito.

PageSpeed score di una pagina d'esempio

Da quando sono stati introdotti i Core Web Vitals, il calcolo del PageSpeed Score ha incluso anche fattori come la stabilità visuale e la responsività di un sito, che è fondamentale tenere in considerazione per la propria ottimizzazione.

L’HTTP/2 rende tutto molto più semplice

Uno dei modi più semplici ed efficienti per migliorare i tempi di caricamento è l’utilizzo del protocollo HTTP/2: il successore dell’HTTP 1.1 è stato infatti progettato per aumentare la performance dei siti grazie ad una serie di potenziamenti non indifferenti.

Ad esempio, utilizzando l’HTTP/2 non è più necessario ridurre il numero di richieste HTTP: l’uso del cosiddetto “Multiplexing” consente il trasferimento simultaneo di 10 file per host nel browser. Questo significa che è possibile trasmettere una qualsiasi quantità di file contemporanei con una singola connessione.

In parole povere, non dovrai necessariamente unire stylesheet e file JavaScript in uno stesso file, o utilizzare un CSS Sprite esteso al posto di tante piccole immagini.

Un’altra caratteristica dell’HTTP/2 è che il server può inviare più risposte ad un utente tramite un’unica richiesta del browser: quindi, oltre a rispondere alla richiesta originale, il server può anche riportare risorse aggiuntive al client, senza che quest’ultimo le debba espressamente richiedere. In questo modo i file da mostrare vengono caricati in anticipo, diminuendo fortemente i tempi di caricamento.

Per saperne di più: The GoogleBot now also supports HTTP/2.

Diminuire le dimensioni del sito

Il metodo principale per ottimizzare il PageSpeed del proprio sito è quello di diminuire la quantità di file da trasferire: più piccolo è il sito, più veloce sarà il suo caricamento. I punti seguenti ti aiuteranno in questo proposito.

Compressione lato server

I formati di testo come HTML, CSS e JavaScript possono essere fortemente ridotti usando una compressione lato server: grazie al cosiddetto “Metodo gzip” (abbreviazione di “GNU zip“), è possibile ridurli in modo semplice e veloce. Un file HTML “zippato” può perdere fino al 70% delle sue dimensioni originarie.

GZIP è attivabile su qualsiasi sito, siccome le Server Application come Apache e NGINX supportano ormai da anni questo tipo di compressione: i browser moderni riescono ad interpretare facilmente i file compressi ed estrarli durante il rendering del sito.

Un metodo ancora più moderno, supportato da tutti i browser attuali, è il cosiddetto algoritmo “Brotli”, creato dagli sviluppatori di Google Zurigo (infatti il nome deriva da un pasticcino svizzero). In confronto a GZIP, Brotli può arrivare a migliorare la compressione del 20%, a parità di velocità di processing.

Compressione delle immagini

I file più pesanti da caricare per un sito sono solitamente le immagini (loghi, foto o illustrazioni che siano): anche questo fattore può essere ulteriormente ottimizzato.

Se usi Photoshop, puoi selezionare la funzione “Save for Web“, subito sotto all’opzione per salvare l’immagine, così da ridurre in modo ottimale la dimensione dell’immagine. Esistono anche dei tool online come TinyPNG o TinyJPG che possono aiutarti ad ottimizzare un’immagine a posteriori.

Inoltre, la selezione del formato gioca a sua volta un ruolo fondamentale nelle dimensioni delle immagini: per quanto riguarda le grafiche, i file PNG sono generalmente più piccoli, mentre per le foto è preferibile il formato JPEG.

Un altro metodo moderno, usato per le immagini fotografiche, traslucide e grafiche, è WebP, la cui compressione è del 30% più efficiente rispetto al JPEG.

Formati come AVIF e JPEG XL si prospettano i futuri successori delle grafiche web: entrambi combinano i vantaggi di JPEG, PNG, Gif e WebP, e hanno tutte le carte in regola per diventare i formati standard dell’internet futuro.

AVIF è un formato per immagini moderno basato sul formato video AV1 ed è già supportato da Google Chrome (a partire dalla versione 85) e da Firefox (a partire dalla versione 86). I file AVIF hanno dimensioni minori del 20% rispetto ai file WebP, e del 50% rispetto ai file JPEG.

Confronto tra formati di immagini

Il nuovo JPEG XL ha una qualità di compressione simile a quella di AVIF, ma offre meno funzionalità aggiuntive. Inoltre, essendo in via di sviluppo, non è ancora supportato da nessun browser.

Incorporare le immagini in risoluzione nativa

Oltre alla compressione corretta, è estremamente importante che le immagini siano scaricate solo nella risoluzione visualizzata: le foto con una risoluzione da fotocamera non dovrebbero mai essere pubblicate sul sito senza essere elaborate, e si dovrebbe evitare di ridimensionare le immagini usando proprietà CSS o attributi HTML.

Se una grafica viene mostrata sul sito con un formato 400×300 pixel, il file corrispondente dovrebbe essere caricato ed incorporato esattamente in questa risoluzione.

Quando si ha a che fare con risoluzioni diverse in dispositivi differenti attraverso layout flessibili, le immagini possono essere caricate nel <source> usando le cosiddette “Responsive Images” attraverso l’elemento <picture>:

<picture>
<source media="(min-width: 800px)" srcset="screenshot.jpg, screenshot-2x.jpg 2x">
  <source media="(min-width: 450px)" srcset="screenshot-small.jpg, screenshot-small-2x.jpg 2x">
  <img src="screenshot-fb.jpg" srcset="screenshot-fb-2x.jpg 2x" alt="Screenshot del sito">
</picture>

Invece di specificare una dimensione e una densità di pixel fisse per le immagini, è possibile indicare le dimensioni di tutte le immagini nell’elemento <img>, aggiungendo un attributo srcset. In questo modo il browser calcolerà automaticamente la densità di pixel effettiva e selezionerà l’immagine migliore per il download.

<img src="screenshot-200.jpg" sizes="50vw"
     srcset="screenshot-100.jpg 100w, screenshot-200.jpg 200w,
             screenshot-400.jpg 400w, screenshot-800.jpg 800w,
             screenshot-1000.jpg 1000w, screenshot-1400.jpg 1400w,
             screenshot-1800.jpg 1800w" alt="Uno Screenshot">

Evita di scaricare dati non necessari

In generale è preferibile evitare di scaricare file dal browser, a meno che non siano effettivamente necessari per mostrare il sito nel modo corretto. Ad esempio, i font web, le icone e le librerie JavaScript dovrebbero essere caricate solo se sono effettivamente in uso sul sito.

Il “Lazy loading” fa in modo che vengano scaricate solo le immagini visibili all’utente: ad esempio, se un’immagine è posta nella parte inferiore della pagina e l’utente non scorre fino a quella parte del sito, il file non verrà caricato affatto.

Nei browser più vecchi questa procedura doveva essere implementata tramite JavaScript, mentre quelli moderni supportano il Lazy Loading grazie agli attributi nelle immagini e nelle iFrames.

Lazy Loading
Fonte

Per quanto riguarda i file CSS molto estesi e le librerie JavaScript, una parte dei dati trasferiti molto spesso non è necessaria e può quindi essere ridotta.

Le applicazioni web moderne possono essere divise automaticamente in pacchetti attraverso un approccio modulare allo sviluppo e l’uso della divisione del codice (usando, ad esempio, Webpack).

Webpack
Fonte

Ridurre la latenza

Latenze e tempi di accesso elevati sono particolarmente dannosi per i tempi di caricamento di un sito, perché nessun dato viene trasferito mentre il browser aspetta la risposta del server, ritardando l’intero processo di caricamento.

Uno degli step più importanti è quello di ottimizzare il cosiddetto “Time To First Byte” (TTBF): questo termine indica il tempo durante il quale il browser deve attendere per ricevere il primo byte di risposta alla sua richiesta. Questo indicatore può essere migliorato con una connessione di qualità e un’infrastruttura di hosting più potente.

La cache lato server, il Rendering lato server e l’uso di generatori di pagine statiche può ridurre il tempo di latenza, generando il codice sorgente per siti dinamici sul server. L’HTML pronto può poi essere memorizzato nella memoria principale (RAM) o su SSD veloci con NVMe, per esempio, e consegnato immediatamente su richiesta.

Tuttavia, non è possibile avere un controllo completo sulla latenza di un sito: se la connessione dell’utente è scarsa, non ci sarà nulla che il provider potrà fare pre migliorare la situazione.

Usando però un CDN (Content Delivery Network), i dati del sito possono essere memorizzati in Data Center distribuiti globalmente e ben collegati, aumentando la probabilità che la connessione dell’utente sia veloce.

Ottimizzare il percorso di rendering

L’ottimizzazione del cosiddetto “Critical Rendering Path” sta diventando sempre più importante per i siti moderni. Con questo termine s’intendono i passi che il browser deve compiere a partire dalla risposta HTML di una pagina, fino al rendering dei pixel sullo schermo.

Prima di tutto, gli elementi devono essere estratti dal documento HTML e trasferiti nel “DOM tree” (Document Object Model); a quel punto viene creato un “CSSOM tree” (CSS Object Model) tramite le informazioni contenute negli stylesheet.

All’esecuzione di JavaScript il Rendering Tree viene terminato generando, a quel punto, il layout (cioè la posizione e la dimensione di tutti gli elementi) e quindi creando la pagina web.

Caricare JavaScript in modo asincrono o in differita

Rinviando gli script che non sono immediatamente necessari, è possibile accelerare enormemente il processo di caricamento visibile all’utente nel browser. Se il Lighthouse Report o il PageSpeed Insights Tool di Google mostra il messaggio “Eliminare le risorse che bloccano il rendering” (“Eliminate render-blocking resources”), gli stili e gli script dovrebbero essere considerati più tardi o ricaricati.

Questo processo viene effettuato con JavaScript usando gli attributi “async” e “defer“:

<script async="async" src="/scripts.js"></script>
<script defer="defer" src="/scripts.js"></script>

A prima vista potrebbe sembrare che i due attributi abbiano lo stesso effetto: la pagina viene caricata molto più velocemente, in quanto lo script non blocca più il processing del restante codice HTML.

La differenza consiste nell’esecuzione degli script.

Con l’attributo “async”, gli script vengono eseguiti immediatamente dopo al processo di caricamento dell’HTML senza rispettare l’ordine d’integrazione. Con l’attributo “defer”, invece, gli script vengono processati nell’ordine previsto, ma solo dopo al caricamento completo del DOM.

Caricamento anticipato dei file necessari

Come già spiegato nella sezione HTTP/2, i file necessari per una pagina HTML possono essere trasmessi nell’Header HTTP della risposta del server, tramite la procedura di server push per il precaricamento. Con Apache, per esempio, questo processo viene eseguito con il seguente codice attraverso il file .htaccess:

<FilesMatch "index.html">
    Header add Link "</css/styles.css>; rel=preload; as=style"
    Header add Link "</js/scripts.js>; rel=preload; as=script"
</FilesMatch>

In alternativa al server push HTTP/2, le risorse necessarie (come i file CSS e JavaScript, le immagini e i font) possono anche essere trasmesse nell’area <head> dell’HTML per il precaricamento:

<link rel="preload" href="style.css" as="style">
<link rel="preload" href="main.js" as="script">
<link rel="preload" href="logo.svg" as="image">
<link rel="preload" href="schrift.woff" as="font">

Caricamento prioritario dei CSS critici

Per impostazione predefinita, i fogli di stile integrati (file CSS) sono risorse che bloccano il rendering, poiché la visualizzazione risulterebbe compromessa senza di essi. Per questo motivo, il CSS richiesto dovrebbe essere diviso in diverse parti:

  1. Una piccola quantità di CSS, necessaria per il “first paint” (cioè il rendering di tutti gli elementi nell’area “above-the-fold”): questo cosiddetto “CSS critico” dovrebbe essere integrato inline nel documento HTML.
  2. Uno stylesheet esterno dovrebbe invece contenere gli altri stili, necessari per il resto della pagina, in modo che possa essere caricato senza bloccare il rendering dell’area critica.

Per caricare gli stylesheet in modo asincrono, la maggior parte dei browser richiede un piccolo JavaScript in combinazione con l’elemento <link> per il precaricamento, così come un fallback NoScript:

<link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="styles.css"></noscript>

In futuro gli import HTML potrebbero essere usati per caricare gli stylesheet che non bloccano il processo di rendering.

Caricamento ottimizzato dei WebFonts

Per utilizzare un font speciale su un sito non preinstallato sul computer dell’utente, è necessario incorporare i cosiddetti WebFonts all’interno del sito. A questo proposito Google offre “Google Fonts“, una directory interattiva con più di 1.000 tipi di font per uso gratuito.

Google Fonts

Per accelerare il processo di caricamento quando si usano i font da Google Fonts (caricati tramite il CDN di Google), è necessario implementare una preconnessione a fonts.gstativ.com in una delle fasi iniziali dell’HTML:

<link rel="preconnect" href="https://fonts.gstatic.com">

In seguito è possibile includere un sottoinsieme specifico di un font (nel codice sottostante, un esempio con il peso 300 del font “Lato”). L’aggiunta “display=swap” assicura che il testo sia immediatamente visibile (inizialmente con un font predefinito), e che non venga nascosto fino al caricamento del font:

<link href="https://fonts.googleapis.com/css2?family=Lato:wght@300&display=swap" rel="stylesheet">

Nel migliore delle ipotesi, però, i WebFonts richiesti verranno memorizzati direttamente sul proprio server e caricati da lì. Questo renderà superflua l’ulteriore risoluzione del dominio (richiesta DNS) così come la configurazione della connessione (connessione TCP) e la crittografia SSL (handshake) con fonts.gstatic.com.

Saltare il layout e utilizzare Content-Visibility

La nuova proprietà CSS “Content-Visibility“, ormai integrata nel Chromium Engine a partire da metà del 2020, è una vera arma segreta quando si tratta di migliorare le prestazioni di caricamento di un sito: questa proprietà permette infatti al browser di saltare il lavoro di rendering di un elemento non ancora visibile.

Il Content-Visibility è come il lazy loading per le immagini, ma riguarda solo la visualizzazione di interi elementi HTML. Il calcolo del layout (rendering) così come il disegno dei pixel (painting) viene saltato se una parte elevata del contenuto si trova fuori dallo schermo, il che rende il caricamento iniziale di una pagina molto più veloce.

content-visibility

Il sito ottimizzato permetterà anche d’interagire molto più velocemente con il contenuto mostrato.

La stabilità visiva

Un argomento relativamente nuovo quando si parla di ottimizzazione del PageSpeed è la stabilità visiva: essa riguarda i cambiamenti nella forma e nella posizione degli elementi mostrati in una pagina.

Durante la fase di ricerca dei Core Web Vitals, è risultato che la maggior parte degli utenti considera particolarmente fastidioso che gli elementi di una pagina (ad esempio link o riquadri cliccabili) si spostino proprio nel momento in cui vengono selezionati. L’utente, infatti, spesso viene portato erroneamente su una pagina sbagliata o effettua un’azione non desiderata, rimanendo frustrato dall’intera esperienza.

Il cosiddetto “Cumulative Layout Shift” (CLS) viene misurato durante il processo di caricamento di una pagina e registrato per l’intero ciclo di vita del sito.

Google usa questa metrica dei Core Web Vitals per valutare proprio l’effetto descritto in precedenza, cioè il prodotto della percentuale dell’area interessata sullo schermo e la percentuale di distanza dello spostamento:

Cumulative Layout Shift fase 1
Il 75% dell’area visibile è interessato dallo spostamento
Cumulative Layout Shift fase 2
La distanza dello spostamento dell’elemento è il 25% del raggio visibile

Il risultato è un valore CLS di 0,1875:

Calcolo del CLS
Screenshot di Kai Spriestersbach

Un errore comune per questo tipo di problema è l’integrazione di un’immagine senza specificare esplicitamente la sua dimensione (altezza e larghezza): gli elementi successivi, come un blocco di testo, verranno quindi spinti verso il basso durante il processo di caricamento, in quanto sopra di essi deve essere prima inserita l’immagine in questione.

Anche i loghi nell’area dell’header della pagina privi di una dimensione fissa, i responsive slider che cambiano le dimensioni dopo il caricamento del contenuto o gli elementi che vengono inseriti successivamente tramite script causano spesso spostamenti di layout indesiderati.

Informazioni aggiuntive sull’argomento

19.01.2023