Usare JavaScript al meglio per avere un sito performante
Non è sempre facile riuscire a mettere insieme la triade Google, Javascript e SEO: il linguaggio di programmazione è particolarmente apprezzato dai tecnici per le possibilità che offre, ma spesso risulta ostico per la scansione del motore di ricerca, che comunque sta compiendo passi in avanti su questo versante, soprattutto con il Googlebot evergreen. Dal blog web.dev arriva però una pratica guida all’ottimizzazione di JavaScript sui siti, utile per limitare potenziali errori che possono impattare negativamente sulle performance del progetto.
I 6 interventi per migliorare le prestazioni di JavaScript
Firmato a più mani, il documento si articola in sei aree di intervento che permettono di limitare gli errori e gli eventuali ostacoli alle prestazioni del sito (sia in senso generale che sul motore di ricerca). In particolare, la scaletta di consigli si concentra su:
- Applicare il caricamento istantaneo con il modello PRPL.
- Precaricare le risorse critiche per migliorare la velocità di caricamento.
- Ridurre i payload JavaScript con lo splitting del codice.
- Rimuovere il codice non utilizzato.
- Minimizzare e comprimere i network payload.
- Offrire codice moderno ai browser moderni per un caricamento più veloce delle pagine.
Il PRPL pattern per l’istant loading
Ad aprire gli spunti è un articolo di Houssein Djirdeh, il Googler che già ci aveva guidato nel percorso di ottimizzazione delle immagini del sito: questa volta, si parla di PRPL pattern e istant loading, elementi che possono fare la differenza in termini di velocità del sito.
L’acronimo PRPL descrive il modello utilizzato per caricare e rendere interattive le pagine Web, che si concretizza in quattro tecniche, che possono essere applicate insieme oppure usati in modo indipendente per ottenere risultati prestazionali:
- Push (or preload) – Invia (o precarica) le risorse più importanti.
- Render – Renderizza il percorso iniziale il più presto possibile.
- Pre-cache – Precarica in cache le risorse rimanenti.
- Lazy Load – Caricamento lento di altri percorsi e risorse non critiche.
Usare Google Lighthouse per controllare la pagina
Il primo passaggio per identificare le opportunità di miglioramento di una pagina attraverso le tecniche PRPL è lanciare Google Lighthouse: se una determinata risorsa viene analizzata e recuperata in ritardo, lo strumento mostra un “controllo non riuscito” su cui possiamo intervenire.
Il precaricamento (preload) è una richiesta di recupero dichiarativa che indica al browser di prelevare una risorsa il prima possibile. È possibile segnalare le risorse critiche aggiungendo un tag <link> con rel=”preload”nell’head del documento HTML, così che il browser possa impostare un livello di priorità appropriato e provare a scaricare la risorsa più presto senza ritardare l’evento window.onload.
Come evitare di ritardare il First Paint
Lighthouse segnala un avviso se trova risorse che ritardano il First Paint, il momento in cui il sito visualizza i pixel sullo schermo: non esiste un’unica soluzione corretta per ridurre First Paint nell’applicazione e potrebbe servire l’integrazione di stili e rendering sul lato server se i vantaggi superano i compromessi per la propria applicazione.
Ad ogni modo, un approccio consigliato è di incorporare JavaScript critico e di differire il resto utilizzando async, nonché di integrare CSS critici utilizzati above-the-fold, oppure di usare server-side render per l’HTML iniziale della pagina: così facendo, si fa visualizzare immediatamente il contenuto all’utente mentre gli script vengono ancora recuperati, analizzati ed eseguiti, ma si potrebbe anche aumentare significativamente il payload del file HTML e danneggiare i parametri di Time to Interactive o il tempo impiegato dall’applicazione per diventare interattiva e rispondere all’input dell’utente.
Consigli per velocizzare il sito
Agendo come proxy, i service workers possono recuperare le risorse direttamente dalla cache anziché dal server durante le visite ripetute: questo non solo consente agli utenti di utilizzare l’applicazione quando sono offline, ma comporta anche tempi di caricamento della pagina più rapidi durante le visite ripetute. Questo processo può essere semplificato usando una library di terze parti, a meno di non disporre di requisiti di cache più complessi di quelli che una libreria può fornire.
L’ultimo passo di questa prima “lezione” è il lazy load: i payload JavaScript di grandi dimensioni sono particolarmente costosi a causa del tempo impiegato dal browser per analizzarli e compilarli, ma dividere l’intero bundle e avviare blocchi di caricamento lento su richiesta permette di inviare un payload JavaScript più piccolo, che contiene solo il codice necessario quando un utente carica inizialmente l’applicazione.
Precaricamento degli asset critici
Il precaricamento degli asset critici garantisce che le risorse più importanti vengano recuperate e scaricate prima dal browser. Quando si apre una pagina Web, il browser richiede il documento HTML da un server, analizza il suo contenuto e invia richieste separate per qualsiasi risorsa di riferimento; gli sviluppatori conoscono già tutte le risorse necessarie alla pagina e quali sono le più importanti, e quindi possono richiedere in anticipo le risorse critiche e accelerare il processo di caricamento.
Il preloading funziona per le risorse generalmente scoperte in ritardo dal browser, a cui invece viene attribuita una priorità; per segnalare il precaricamento si può aggiungere un tag <link> con rel=”preload” nell’head del documento HTML, così che il browser memorizzi nella cache le risorse e le renda immediatamente disponibili quando necessario.
Differenze tra preloading, preconnect e prefetch
Al contrario di preconnect e prefetch, ad esempio, che sono suggerimenti eseguiti dal browser nel modo che ritiene opportuno, il preload è obbligatorio. I browser moderni sono già abbastanza abili nel dare la priorità alle risorse, ecco perché è importante usare preloading con parsimonia, applicarlo solo le risorse più importanti e verificare sempre l’impatto con test reali.
Tra le risorse che si possono precaricare citiamo font o immagini in background definiti in CSS, file CSS e file JavaScript: in questo ultimo caso, la procedura è utile per separare il recupero dall’esecuzione e può migliorare metriche come Time to Interactive.
Ridurre i paylods JavaScript dividendo il codice
Sappiamo che la velocità sul web è fondamentale e più del 50% degli utenti abbandona un sito Web se il caricamento richiede più di 3 secondi. Come ci ricorda Houssein Djirdeh, l’invio di payload JavaScript di grandi dimensioni influisce in modo significativo sulla rapidità del sito, ma è possibile dividere il pacchetto in più pezzi e inviare solo ciò che è necessario all’inizio per migliorare questo aspetto.
Anziché spedire tutto il JavaScript all’utente al momento in viene caricata la prima pagina dell’applicazione, possiamo cioè splittare il bundle per inviare solo il codice necessario per il percorso iniziale, riducendo al minimo la quantità di script da analizzare e compilare e, quindi, rendere più veloci i tempi di caricamento della pagina. Questa operazione può essere eseguita con vari module bundlers, come webpack, Parcel and Rollup, che usano importazioni dinamiche.
Rimuovere il codice non utilizzato
Registri come npm consentono a tutti di scaricare e usare facilmente più di mezzo milione di pacchetti JavaScript, ma spesso includendo anche library non pienamente utilizzate: il processo di miglioramento delle performance del sito passa anche dall’analisi del codice non usato e delle librerie non necessarie, che tolgono spazio e tempo.
Minimizzare e comprimere i payload di rete
Ci sono due tecniche specifiche per migliorare le prestazioni della tua pagina Web, la minimizzazione (minification) e la compressione dei dati, che possono ridurre le dimensioni del carico utile e, a sua volta, migliora i tempi di caricamento della pagina.
È sempre Lighthouse a segnalare se sulla pagina ci sono eventuali risorse CSS o JavaScript che possono essere minimizzate: se opportuno, si procede alla minification, un processo di rimozione degli spazi bianchi e di qualsiasi codice non necessario per creare un file di codice più piccolo ma perfettamente valido.
La compressione dei dati funziona attraverso un algoritmo che appunto comprime le risorse e i file possono essere limitati in modo dinamico o statico: entrambi gli approcci hanno dei vantaggi e degli svantaggi e quindi si può usare quello più adatto alle proprie esigenze.
Nel metodo dinamico, le risorse sono compresse al volo quando vengono richieste dal browser: questo può essere più semplice rispetto a processi manuali o di compilazione, ma può causare ritardi se si utilizzano livelli di compressione elevati. La compressione statica riduce e salva le risorse in anticipo: il processo di compilazione può essere più lungo, ma non ci saranno ritardi quando il browser recupera la risorsa compressa.
Un codice moderno per i browser moderni
Costruire siti Web che funzionano bene su tutti i principali browser è un principio fondamentale di un ecosistema web aperto, scrive Houssein Djirdeh: questo implica un lavoro ulteriore per garantire che tutto il codice scritto sia supportato in ciascun browser da scegliere come target. In termini pratici, chi desidera utilizzare le nuove funzionalità del linguaggio JavaScript deve necessariamente trascrivere tali feature in formati retro-compatibili per i browser che non le supportano ancora.
Uno strumento che permette di compilare il codice che contiene una sintassi più recente in codice comprensibile per browser e ambienti diversi è Babel, il cui contraltare si chiama Lebab (appunto Babel scritto al contrario), che è una libreria separata che converte il codice più vecchio in una sintassi più recente.