Prestazioni web semplificate - Google I/O 2018

In occasione di Google IO 2018, abbiamo presentato una carrellata di strumenti, librerie e tecniche di ottimizzazione che semplificano il miglioramento delle prestazioni web. Qui li spieghiamo utilizzando l'app Oodles Theater. Parleremo anche dei nostri esperimenti con il caricamento predittivo e della nuova iniziativa Guess.js.

Addy Osmani
Addy Osmani
Ewa Gasperowicz

Nell'ultimo anno abbiamo cercato di capire come rendere il web più veloce e con prestazioni migliori. Questo approccio ha portato alla creazione di nuovi strumenti, approcci e librerie che vorremmo condividere con te in questo articolo. Nella prima parte, ti mostreremo alcune tecniche di ottimizzazione che abbiamo utilizzato nella pratica durante lo sviluppo dell'app Oodles Theater. Nella seconda parte, parleremo dei nostri esperimenti con il caricamento predittivo e della nuova iniziativa Guess.js.

La necessità di prestazioni

Internet diventa sempre più pesante e pesante ogni anno. Se controlliamo lo stato del web, possiamo notare che una pagina mediana sui dispositivi mobili pesa circa 1,5 MB, e per la maggior parte sono JavaScript e immagini.

La crescente dimensione dei siti web, insieme ad altri fattori come la latenza di rete, le limitazioni della CPU, i pattern di blocco del rendering o il codice superfluo di terze parti, contribuiscono al complicato puzzle del rendimento.

Per la maggior parte degli utenti, la velocità è ai vertici della gerarchia UX per le proprie esigenze. Ciò non sorprende, perché non puoi fare molto fino a quando una pagina non è stata caricata completamente. Non si può ricavare valore dalla pagina, non si può ammirare la sua estetica.

piramide UX
Fig. 1. Quanto è importante la velocità per gli utenti? (La velocità conta, Vol. 3)

Sappiamo che le prestazioni sono importanti per gli utenti, ma può anche sembrare un segreto che scopre dove iniziare l'ottimizzazione. Fortunatamente, esistono strumenti che possono aiutarti lungo il percorso.

Lighthouse: una base per il flusso di lavoro relativo alle prestazioni

Lighthouse fa parte di Chrome DevTools che ti consente di eseguire un controllo del tuo sito web e ti dà suggerimenti su come migliorarlo.

Di recente abbiamo lanciato una serie di nuovi controlli delle prestazioni che sono davvero utili nel flusso di lavoro di sviluppo quotidiano.

Nuovi controlli di Lighthouse
Fig. 2. Nuovi controlli di Lighthouse

Vediamo come sfruttarli con un esempio pratico: l'app Oodles Theater. È una piccola app web demo in cui puoi provare alcuni dei nostri doodle di Google interattivi preferiti e persino giocare a un paio di giochi.

Durante la creazione dell'app, volevamo assicurarci che fosse il più efficiente possibile. Il punto di partenza per l'ottimizzazione era il report Lighthouse.

Report Lighthouse per l'app Oodles
Fig. 3. Report Lighthouse per l'app Oodles

Le prestazioni iniziali della nostra app come indicato nel report Lighthouse erano piuttosto terribili. Su una rete 3G, l'utente doveva attendere 15 secondi prima che la prima visualizzazione significativa o che l'app diventasse interattiva. Lighthouse ha evidenziato moltissimi problemi relativi al nostro sito e il punteggio complessivo delle prestazioni di 23 rispecchia esattamente questo aspetto.

La pagina pesava circa 3,4 MB: avevamo disperatamente bisogno di tagliare i grassi.

È iniziata la nostra prima sfida in termini di rendimento: individuare elementi che possiamo rimuovere facilmente senza influire sull'esperienza complessiva.

Opportunità di ottimizzazione del rendimento

Rimuovi le risorse non necessarie

Esistono alcuni elementi ovvi che possono essere rimossi in sicurezza: spazi vuoti e commenti.

Utili derivanti dalla minimizzazione
Fig. 4. Minimizza e comprimi JavaScript e CSS

Lighthouse evidenzia questa opportunità nel controllo CSS e JavaScript unificato. Stavamo utilizzando webpack per il processo di compilazione, quindi, per ottenere la minimizzazione, abbiamo semplicemente utilizzato il plug-in Uglify JS.

La minimizzazione è un'attività comune, quindi dovresti essere in grado di trovare una soluzione già pronta per qualsiasi processo di build utilizzato.

Un altro controllo utile in questo spazio è Attiva la compressione del testo. Non c'è motivo di inviare file non compressi e la maggior parte delle CDN lo supporta fin da subito.

Stavamo utilizzando Firebase Hosting per ospitare il nostro codice e Firebase abilita gzipping per impostazione predefinita, quindi, pur ospitando il nostro codice su una CDN ragionevole, lo abbiamo ottenuto senza costi.

Sebbene gzip sia un modo molto popolare di comprimere, anche altri meccanismi come Zopfli e Brotli stanno avendo successo. Brotli è supportato nella maggior parte dei browser e puoi utilizzare un programma binario per precomprimere gli asset prima di inviarli al server.

Usa criteri di cache efficienti

Il passo successivo è stato quello di assicurarci di non inviare due volte le risorse se non sono necessarie.

Il controllo Criterio cache inefficiente in Lighthouse ci ha aiutato a notare che avremmo potuto ottimizzare le nostre strategie di memorizzazione nella cache per ottenere esattamente questo risultato. Impostando un'intestazione con scadenza massima nel nostro server, ci siamo assicurati che, in una visita ripetuta, l'utente possa riutilizzare le risorse scaricate in precedenza.

Idealmente, dovresti cercare di memorizzare nella cache il maggior numero possibile di risorse in modo sicuro per il periodo di tempo più lungo possibile e fornire token di convalida per una riconvalida efficiente delle risorse aggiornate.

Rimuovi il codice inutilizzato

Finora abbiamo rimosso le parti più ovvie del download non necessario, ma che dire delle parti meno ovvie? Ad esempio, codice inutilizzato.

Copertura del codice in DevTools
Fig. 5. Controlla la copertura del codice.

A volte includiamo nel codice delle nostre app non necessario. Questo accade soprattutto se lavori sull'app per un periodo di tempo più lungo, se il tuo team o le tue dipendenze cambiano e a volte rimane una libreria orfano. È esattamente quello che ci è successo.

All'inizio avevamo usato la libreria di Material Componenti per realizzare un prototipo della nostra app. Con il passare del tempo siamo passati a un aspetto più personalizzato e ci siamo dimenticati del tutto di quella libreria. Fortunatamente, il controllo della copertura del codice ci ha aiutato a riscoprirlo nel nostro bundle.

Puoi controllare le statistiche sulla copertura del codice in DevTools, sia per il runtime che per il tempo di caricamento della tua applicazione. Nello screenshot in basso sono presenti le due grandi strisce rosse: oltre il 95% del nostro CSS era inutilizzato e molto codice JavaScript.

Lighthouse ha inoltre rilevato questo problema nel controllo delle regole CSS inutilizzate. Ha mostrato un potenziale risparmio di oltre 400 kB. Siamo tornati al nostro codice e abbiamo rimosso sia la parte JavaScript che CSS della libreria.

Se rilasciamo un adattatore MVC, i nostri stili scendono a 10 kB
Fig. 6. Se rilasciamo un adattatore MVC, i nostri stili scendono a 10 kB!

In questo modo, il nostro bundle CSS si è ridotto di 20 volte, il che è ideale per un piccolo commit di due righe.

Ovviamente, ci ha fatto salire il nostro punteggio delle prestazioni e anche il report Tempo all'interattività è migliorato notevolmente.

Tuttavia, con modifiche come questa, non è sufficiente controllare solo le metriche e i punteggi. La rimozione del codice effettivo non è mai priva di rischi, quindi devi sempre fare attenzione alle potenziali regressioni.

Il nostro codice non è stato utilizzato nel 95%, c'è ancora questo 5% da qualche parte. A quanto pare uno dei nostri componenti usava ancora gli stili di quella libreria, ovvero le piccole frecce nel cursore dei doodle. Tuttavia, poiché era così piccolo, potevamo semplicemente incorporarli manualmente nei pulsanti.

I pulsanti si sono rotti a causa della raccolta mancante
Fig. 7. Un componente stava ancora utilizzando la libreria rimossa

Quindi, se rimuovi il codice, assicurati di disporre di un flusso di lavoro di test appropriato per evitare potenziali regressioni visive.

Evita payload di rete enormi

Sappiamo che risorse di grandi dimensioni possono rallentare i caricamenti delle pagine web. Possono costare ai nostri utenti e possono avere un grande impatto sui loro piani dati, perciò è fondamentale essere consapevoli.

Lighthouse è stato in grado di rilevare un problema con alcuni payload di rete utilizzando il controllo Payload di rete Enorme.

Rileva payload di rete enormi
Fig. 8. Rileva payload di rete enormi

Qui abbiamo visto che avevamo più di 3 MB di codice che veniva spedito, il che è una quantità notevole, soprattutto sui dispositivi mobili.

All'inizio di questo elenco, Lighthouse ha evidenziato che avevamo un bundle del fornitore JavaScript costituito da 2 MB di codice non compresso. Questo problema è anche evidenziato dal webpack.

come si suol dire: la richiesta più rapida è quella che non viene effettuata.

Idealmente, dovresti misurare il valore di ogni singolo asset che mostri ai tuoi utenti, misurarne il rendimento e decidere se vale la pena di mostrarlo agli utenti. Perché a volte questi asset possono essere differiti, caricati in modo lento o elaborati durante il tempo di inattività.

Nel nostro caso, dato che abbiamo a che fare con molti bundle JavaScript, abbiamo avuto la fortuna perché la community JavaScript ha un set completo di strumenti di controllo dei bundle JavaScript.

Controllo del bundle JavaScript
Fig. 9. Controllo dei bundle JavaScript

Abbiamo iniziato con lo strumento di analisi dei bundle webpack, che ci ha comunicato che stavamo includendo una dipendenza chiamata Unicode, che era di 1,6 MB di JavaScript analizzato.

Siamo quindi passati all'editor e utilizzando il plug-in dei costi di importazione per il codice visivo siamo riusciti a visualizzare il costo di ogni modulo che stavamo importando. Questo ci ha permesso di scoprire quale componente includeva il codice che fa riferimento a questo modulo.

Siamo quindi passati a un altro strumento, BundlePhobia. Si tratta di uno strumento che ti consente di inserire il nome di qualsiasi pacchetto di Gestione dei partner di rete e di vedere effettivamente le stime delle sue dimensioni minimizzate e compresse con gzip. Abbiamo trovato un'alternativa valida per il modulo slug che stavamo usando, che pesava solo 2,2 kB, quindi l'abbiamo sostituita.

Ciò ha avuto un grande impatto sul nostro rendimento. In seguito a questa modifica e alla scoperta di altre opportunità per ridurre le dimensioni del bundle JavaScript, abbiamo risparmiato 2,1 MB di codice.

Abbiamo registrato miglioramenti complessivi del 65%, una volta che avete preso in considerazione le dimensioni compresse e minimizzate di questi bundle. E abbiamo scoperto che ne valeva la pena.

Quindi, in generale, cerca di eliminare i download non necessari nei siti e nelle app. Crea un inventario dei tuoi asset e misura il loro impatto sul rendimento può fare una grande differenza, quindi assicurati di controllare gli asset abbastanza regolarmente.

Tempi di avvio JavaScript ridotti con la suddivisione del codice

Anche se i payload di rete di grandi dimensioni possono avere un grande impatto sulla nostra app, c'è un altro aspetto che può avere un impatto davvero importante, ovvero JavaScript.

JavaScript è l'asset più costoso. Sui dispositivi mobili, se invii grandi bundle di JavaScript, può ritardare l'interazione degli utenti con i componenti dell'interfaccia utente. Ciò significa che possono toccare l'interfaccia utente senza che succeda nulla di significativo. Per noi è importante capire perché JavaScript costa così tanto.

È il modo in cui un browser elabora JavaScript.

Elaborazione JavaScript
Fig. 10. Elaborazione JavaScript

Prima di tutto dobbiamo scaricare lo script. Abbiamo un motore JavaScript che deve analizzare il codice, compilarlo ed eseguirlo.

Queste fasi non richiedono troppo tempo su un dispositivo di fascia alta, come un computer desktop o un laptop, magari anche un telefono di fascia alta. Su un cellulare medio, questo processo può richiedere da cinque a dieci volte più a lungo. Questo è ciò che ritarda l'interattività, quindi è importante provare a ridurle.

Per aiutarti a rilevare questi problemi con la tua app, abbiamo introdotto un nuovo controllo del tempo di avvio di JavaScript in Lighthouse.

Tempo di avvio di JavaScript
Fig. 11. Controllo del tempo di avvio di JavaScript

Nel caso dell'app Oodle, ci è stato comunicato che il tempo dedicato all'avvio di JavaScript è stato di 1,8 secondi. Ciò era dovuto al fatto che eseguivamo l'importazione statica di tutte le route e tutti i componenti in un bundle JavaScript monolitico.

Una tecnica per risolvere questo problema è utilizzare la suddivisione del codice.

La suddivisione del codice è come la pizza

La suddivisione del codice è un'idea che, invece di fornire agli utenti un intero codice JavaScript, e se offrissi loro solo una fetta alla volta, in base alle necessità?

La suddivisione del codice può essere applicata a livello di route o di componente. Funziona benissimo con React e React Loadable, Vue.js, Angular, Polymer, Preact e molte altre librerie.

Abbiamo integrato la suddivisione del codice nella nostra applicazione, siamo passati dalle importazioni statiche alle importazioni dinamiche, consentendoci di inserire il codice di caricamento in modo asincrono quando ne avevamo bisogno.

Suddivisione del codice con importazioni dinamiche
Fig. 13. Suddivisione del codice con importazioni dinamiche

L'impatto di questo cambiamento è stato la riduzione delle dimensioni dei nostri bundle, ma anche i tempi di avvio di JavaScript. Lo ha ridotto a 0,78 secondi, rendendo l'app più veloce del 56%.

In generale, se stai creando un'esperienza con JavaScript, assicurati di inviare il codice solo all'utente di cui ha bisogno.

Approfitta di concetti come la suddivisione del codice, esplora idee come il tremolio degli alberi e consulta il repository webpack-libs-optimizeds per alcune idee su come ridurre le dimensioni della libreria se utilizzi il webpack.

Ottimizza immagini

Barzelletta sul rendimento del caricamento delle immagini

Nell'app Oodle stiamo usando molte immagini. Sfortunatamente, Lighthouse era molto meno entusiasta di questo servizio. Effettivamente, non abbiamo superato tutti e tre i controlli relativi alle immagini.

Abbiamo dimenticato di ottimizzare le immagini, non le abbiamo dimensionate correttamente e abbiamo anche potuto migliorare utilizzando altri formati dell'immagine.

Controlli delle immagini
Fig. 14. Controlli delle immagini Lighthouse

Abbiamo iniziato con l'ottimizzazione delle nostre immagini.

Per una serie di ottimizzazioni una tantum, puoi usare strumenti visivi come ImageOptim o XNConvert.

Un approccio più automatizzato consiste nell'aggiungere un passaggio di ottimizzazione delle immagini al processo di compilazione, con librerie come imagemin.

In questo modo, avrai la certezza che le immagini aggiunte in futuro verranno ottimizzate automaticamente. Alcune reti CDN, ad esempio Akamai o soluzioni di terze parti come Cloudinary, Fastly o Uploadcare, offrono soluzioni complete per l'ottimizzazione delle immagini, così puoi anche semplicemente ospitare le tue immagini su quei servizi.

Se non vuoi farlo a causa dei costi o dei problemi di latenza, progetti come Thumbor o Imageflow offrono alternative in self-hosting.

Ottimizzazione prima e dopo
Fig. 15. Ottimizzazione prima e dopo

Proprio così, nel webpack il nostro PNG di sfondo è stato contrassegnato come grande. Dopo averlo ridimensionato correttamente in base all'area visibile e averlo eseguito tramite ImageOptim, siamo scesi a 100 kb, che è accettabile.

La ripetizione di questa procedura per più immagini sul nostro sito ci ha consentito di ridurre significativamente il peso complessivo della pagina.

Utilizza il formato giusto per i contenuti animati

Le GIF possono diventare molto costose. Sorprendentemente, il formato GIF non è mai stato pensato come piattaforma di animazione. Pertanto, il passaggio a un formato video più adatto permette di risparmiare significativo in termini di dimensioni dei file.

Nell'app Oodle, utilizzavamo una GIF come sequenza introduttiva nella home page. Secondo Lighthouse, potremmo risparmiare oltre 7 MB passando a un formato video più efficiente. Il nostro clip pesava circa 7,3 MB, decisamente troppo per qualsiasi sito web ragionevole, quindi l'abbiamo trasformato in un elemento video con due file sorgente: un mp4 e WebM per un supporto più ampio del browser.

Sostituisci le GIF animate con un video
Fig. 16. Sostituisci le GIF animate con un video

Abbiamo utilizzato lo strumento FFmpeg per convertire la GIF di animazione nel file mp4. Il formato WebM ti offre risparmi ancora maggiori, l'API ImageOptim può aiutarti a farlo.

ffmpeg -i animation.gif -b:v 0 -crf 40 -vf scale=600:-1 video.mp4

Grazie a questa conversione, siamo riusciti a risparmiare oltre l'80% del nostro peso complessivo. Questo ci ha portato a circa 1 MB.

Tuttavia, 1 MB è una risorsa di grandi dimensioni per il push down del cavo, soprattutto per un utente con una larghezza di banda limitata. Fortunatamente, abbiamo potuto utilizzare l'API Effective Type per capire che hanno una larghezza di banda lenta e fornire loro un JPEG molto più piccolo.

Questa interfaccia utilizza i valori del tempo di round trip e del downing effettivi per stimare il tipo di rete utilizzato dall'utente. Restituisce semplicemente una stringa, 2G, 2G, 3G o 4G lenti. Quindi, a seconda di questo valore, se l'utente utilizza una connessione 4G inferiore a 4G, potremmo sostituire l'elemento video con l'immagine.

if (navigator.connection.effectiveType) { ... }

Rimuove un po' l'esperienza, ma almeno il sito è utilizzabile su una connessione lenta.

Caricamento lento delle immagini fuori schermo

Caroselli, dispositivi di scorrimento o pagine molto lunghe spesso caricano le immagini, anche se l'utente non le vede immediatamente sulla pagina.

Lighthouse segnalerà questo comportamento nel controllo delle immagini fuori schermo. Puoi anche vederlo nel riquadro Network di DevTools. Se vedi tante immagini in arrivo, ma solo alcune sono visibili sulla pagina, significa che potresti caricarle lentamente.

Il caricamento lento non è ancora supportato in modo nativo nel browser, quindi dobbiamo usare JavaScript per aggiungere questa funzionalità. Abbiamo utilizzato la libreria Lazysizes per aggiungere un comportamento di caricamento lento alle nostre copertine Oodle.

<!-- Import library -->
import lazysizes from 'lazysizes'  <!-- or -->
<script src="lazysizes.min.js"></script>

<!-- Use it -->

<img data-src="image.jpg" class="lazyload"/>
<img class="lazyload"
    data-sizes="auto"
    data-src="image2.jpg"
    data-srcset="image1.jpg 300w,
    image2.jpg 600w,
    image3.jpg 900w"/>

Lazysize è una strategia intelligente perché non solo tiene traccia delle modifiche di visibilità dell'elemento, ma precarica in modo proattivo gli elementi che si trovano vicino alla visualizzazione per un'esperienza utente ottimale. Offre inoltre un'integrazione facoltativa di IntersectionObserver, che ti offre ricerche di visibilità molto efficienti.

Dopo questa modifica, le nostre immagini verranno recuperate on demand. Se vuoi approfondire questo argomento, consulta images.guide, una risorsa molto utile e completa.

Il browser della guida per fornire risorse critiche in anticipo

Non tutti i byte inviati al browser hanno lo stesso grado di importanza e il browser lo sa. Molti browser utilizzano l'euristica per decidere quale sia il primo argomento da recuperare. Perciò a volte recuperano il CSS prima delle immagini o degli script.

Un elemento che potrebbe essere utile è noi, come autori della pagina, che indichiamo al browser ciò che è davvero importante per noi. Fortunatamente, negli ultimi due anni i fornitori di browser hanno aggiunto una serie di funzionalità per aiutarci, ad esempio suggerimenti sulle risorse come link rel=preconnect, preload o prefetch.

Queste funzionalità offerte alla piattaforma web consentono al browser di recuperare la cosa giusta al momento giusto e possono essere un po' più efficienti di alcuni approcci basati sulla logica e con caricamento personalizzato eseguiti tramite script.

Vediamo in che modo Lighthouse ci guida verso l'utilizzo efficace di alcune di queste funzionalità.

La prima cosa che Lighthouse ci dice di fare è evitare più costosi viaggi di andata e ritorno a qualsiasi origine.

Evita più costosi viaggi di andata e ritorno verso qualsiasi luogo di partenza
Fig. 17. Evita più e costosi viaggi di andata e ritorno verso qualsiasi luogo di partenza.

Nel caso dell'app Oodle, in realtà usiamo in modo massiccio Google Fonts. Ogni volta che rilasci un foglio di stile Carattere Google nella tua pagina, questo si connette a un massimo di due sottodomini. Lighthouse ci dice che, se riuscissimo a riscaldare la connessione, potremmo risparmiare fino a 300 millisecondi nel tempo di connessione iniziale.

Sfruttando la preconnessione link rel, possiamo mascherare in modo efficace la latenza di connessione.

Soprattutto con Google Fonts, in cui il codice CSS per i caratteri è ospitato su googleapis.com e le risorse per i caratteri sono ospitate su Gstatic, questo può avere un grande impatto. Quindi abbiamo applicato questa ottimizzazione e ci siamo tagliati qualche centinaio di millisecondi.

Lighthouse suggerisce inoltre che le richieste chiave vengono precaricate.

Precarica le richieste chiave
Fig. 18. Precarica le richieste chiave

<link rel=preload> è davvero potente: indica al browser che è necessaria una risorsa nell'ambito della navigazione corrente e tenta di ottenere il recupero del browser il prima possibile.

Lighthouse ci dice che dobbiamo precaricare le nostre risorse chiave per i caratteri web, dato che stiamo caricando due caratteri web.

Il precaricamento in un carattere web è simile al seguente: specificando rel=preload, passi in as con il tipo di carattere e poi specifichi il tipo di carattere che vuoi caricare, ad esempio woff2.

L'impatto che questo cambiamento può avere sulla tua pagina è piuttosto netto.

Impatto del precaricamento delle risorse
Fig. 19. Impatto del precaricamento delle risorse

In genere, se i caratteri web sono fondamentali per la pagina, se i caratteri web sono fondamentali per la pagina senza utilizzare link rel preload, il browser deve prima recuperare il codice HTML, analizzare il CSS e, molto più tardi, recupera i caratteri web.

Utilizzando link rel preload, non appena il browser avrà analizzato il tuo HTML, potrà iniziare a recuperare i caratteri web molto prima. La nostra app ha ridotto di un secondo il tempo necessario a eseguire il rendering del testo con i nostri caratteri web.

Se provi a precaricare i caratteri utilizzando Google Fonts, non è così semplice, c'è un problema.

Gli URL dei caratteri Google specificati nelle schermate dei caratteri nei fogli di stile sono qualcosa che il team responsabile per i caratteri aggiorna con una certa regolarità. Questi URL possono scadere o essere aggiornati con una frequenza regolare, pertanto ti consigliamo di adottare l'hosting dei caratteri web per avere il controllo completo dell'esperienza di caricamento dei caratteri. Questa opzione può essere molto utile perché ti consente di accedere a funzionalità come il precaricamento di link rel.

Nel nostro caso, lo strumento Helper dei caratteri web di Google ci è stato davvero utile per aiutarci a mettere offline alcuni di questi caratteri web e a configurarli localmente, quindi dai un'occhiata a questo strumento.

Sia che utilizzi caratteri web come parte delle tue risorse critiche, sia che usi JavaScript, prova ad aiutare il browser a fornire le risorse critiche il prima possibile.

Sperimentale: suggerimenti di priorità

Abbiamo qualcosa di speciale da condividere con te oggi. Oltre a funzionalità come i suggerimenti delle risorse e il precaricamento, stiamo lavorando a una nuovissima funzionalità sperimentale del browser, ovvero i suggerimenti prioritari.

Imposta la priorità per i contenuti inizialmente visibili
Fig. 20. Suggerimenti sulla priorità

Si tratta di una nuova funzionalità che consente di suggerire al browser l'importanza di una risorsa. Espone un nuovo attributo (importanza) con i valori Low, High o Auto.

Questo ci consente di comunicare la riduzione della priorità delle risorse meno importanti, ad esempio stili non critici, immagini o chiamate API di recupero per ridurre i conflitti. Possiamo anche dare priorità a elementi più importanti, come le immagini hero.

Nel caso della nostra app Oodle, questo ci ha portato a un punto pratico in cui potevamo ottimizzare.

Imposta la priorità per i contenuti inizialmente visibili
Fig. 21. Imposta la priorità per i contenuti visibili inizialmente.

Prima di aggiungere il caricamento lento alle nostre immagini, ciò che faceva il browser era questo carosello di immagini con tutti i nostri doodle e il browser recuperava tutte le immagini all'inizio del carosello con priorità elevata all'inizio. Sfortunatamente, erano le immagini al centro del carosello le più importanti per l'utente. Abbiamo quindi impostato l'importanza di queste immagini di sfondo su molto bassa, quelle in primo piano molto elevate, l'impatto di due secondi su una connessione 3G lenta e la velocità con cui siamo riusciti a recuperare e visualizzare le immagini. Quindi è stata un'esperienza positiva.

Ci auguriamo di rendere disponibile questa funzionalità in Canary tra qualche settimana, quindi tieni d'occhio questa novità.

Implementare una strategia di caricamento dei caratteri web

La tipografia è fondamentale per un buon design e, se usi caratteri web, idealmente non vuoi bloccare il rendering del tuo testo né mostrare testo invisibile.

Ora lo evidenziamo in Lighthouse, con il controllo Evita testo invisibile durante il caricamento dei caratteri web.

Evita testo invisibile durante il caricamento dei caratteri web
Fig. 22. Evita testo invisibile durante il caricamento dei caratteri web

Se carichi i caratteri web utilizzando un blocco di caratteri, consenti al browser di decidere cosa fare se il recupero richiede molto tempo. Alcuni browser attendono fino a tre secondi prima di ricorrere a un carattere di sistema e, una volta scaricato, lo passano al carattere.

Cerchiamo di evitare questo testo invisibile, quindi in questo caso non saremmo riusciti a vedere i classici doodle di questa settimana se il carattere web avesse impiegato troppo tempo. Per fortuna, con una nuova funzionalità chiamata font-display, puoi avere un maggiore controllo su questo processo.

    @font-face {
      font-family: 'Montserrat';
      font-style: normal;
      font-display: swap;
      font-weight: 400;
      src: local('Montserrat Regular'), local('Montserrat-Regular'),
          /* Chrome 26+, Opera 23+, Firefox 39+ */
          url('montserrat-v12-latin-regular.woff2') format('woff2'),
            /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
          url('montserrat-v12-latin-regular.woff') format('woff');
    }

La visualizzazione dei caratteri ti aiuta a decidere come verranno visualizzati i caratteri web di riserva in base al tempo necessario per lo scambio.

In questo caso stiamo usando lo scambio di visualizzazione dei caratteri. Scambia conferisce al carattere un periodo di blocco di zero secondi e un periodo di scambio infinito. Ciò significa che il browser disegnerà il testo piuttosto immediatamente con un carattere di riserva se il caricamento del carattere richiede un po' di tempo. e lo sostituirà quando il carattere sarà disponibile.

L'utilità dell'app ci ha consentito di mostrare fin da subito del testo significativo e di passare al carattere web una volta pronto.

Risultato di visualizzazione del carattere
Fig. 23. Risultato di visualizzazione del carattere

In generale, se utilizzi caratteri web, come gran parte del web, adotta una buona strategia di caricamento dei caratteri web.

Esistono molte funzionalità della piattaforma web che puoi usare per ottimizzare l'esperienza di caricamento per i caratteri, ma dai un'occhiata anche al repository Web Font Recipes di Zach Skinman, perché è davvero fantastico.

Riduci gli script che bloccano la visualizzazione

Ci sono altre parti della nostra applicazione che potremmo eseguire prima nella catena di download per fornire almeno un'esperienza utente di base un po' prima.

Nella barra della sequenza temporale di Lighthouse puoi vedere che durante questi primi secondi, quando tutte le risorse sono in fase di caricamento, l'utente non può davvero vedere alcun contenuto.

Riduzione delle opportunità per i fogli di stile che bloccano la visualizzazione
Fig. 24. Riduci le opportunità dei fogli di stile che bloccano la visualizzazione

Il download e l'elaborazione di fogli di stile esterni impediscono al nostro processo di rendering di fare progressi.

Possiamo provare a ottimizzare il nostro percorso di rendering critico caricando alcuni degli stili con un po' di anticipo.

Se estraiamo gli stili responsabili di questo rendering iniziale e li incorporiamo nel nostro codice HTML, il browser è in grado di visualizzarli immediatamente senza attendere l'arrivo dei fogli di stile esterni.

Nel nostro caso, abbiamo utilizzato un modulo Gestione dei partner di rete chiamato Critical per incorporare i nostri contenuti critici in index.html durante un passaggio di creazione.

Questo modulo ha svolto la maggior parte del lavoro più impegnativo, ma è stato comunque un po' difficile farlo funzionare senza problemi su più percorsi.

Se non fai attenzione o se la struttura del tuo sito è molto complessa, potrebbe essere davvero difficile introdurre questo tipo di pattern se non avevi pianificato l'architettura della shell dell'app dall'inizio.

Ecco perché è così importante prendere in considerazione il rendimento fin da subito. Se non prevedi di ottimizzare il rendimento fin dall'inizio, c'è un'alta possibilità che incontrerai problemi in seguito.

Alla fine il nostro rischio è stato ripagato, ma siamo riusciti a far funzionare l'app e l'app ha iniziato a distribuire contenuti molto prima, migliorando in modo significativo il tempo che abbiamo impiegato per la prima colorazione.

Il risultato

Questo era un lungo elenco di ottimizzazioni del rendimento che abbiamo applicato al nostro sito. Diamo un'occhiata ai risultati. Ecco come la nostra app si è caricata su un dispositivo mobile di medie dimensioni su una rete 3G, prima e dopo l'ottimizzazione.

Il punteggio delle prestazioni di Lighthouse è aumentato da 23 a 91. Si tratta di ottimi progressi in termini di velocità. Tutte le modifiche sono state alimentate da noi controlli e seguindo continuamente il report Lighthouse. Se vuoi vedere come abbiamo implementato tecnicamente tutti i miglioramenti, non esitare a dare un'occhiata al nostro repository, in particolare i PR arrivati lì.

Prestazioni predittive: esperienze utente basate sui dati

Riteniamo che il machine learning rappresenti un'opportunità entusiasmante per il futuro in molte aree. Un'idea che speriamo possa stimolare ulteriori sperimentazioni in futuro è che dati reali possono davvero guidare le esperienze utente che stiamo creando.

Oggi prendiamo molte decisioni arbitrarie su cosa l'utente potrebbe volere o avere bisogno e quindi su cosa vale la pena precaricare, precaricare o pre-memorizzare nella cache. Se pensiamo bene, possiamo dare priorità a una piccola quantità di risorse, ma è davvero difficile scalarla per estenderla all'intero sito web.

Attualmente disponiamo di dati per ottimizzare le nostre ottimizzazioni. Utilizzando l'API di reporting di Google Analytics, possiamo dare un'occhiata alla prossima pagina principale e alle percentuali di uscita per qualsiasi URL del nostro sito e, di conseguenza, trarre conclusioni sulle risorse a cui dare la priorità.

Se combiniamo questo metodo con un buon modello di probabilità, evitiamo di sprecare i dati dell'utente eseguendo il precaricamento eccessivo dei contenuti. Possiamo sfruttare i dati di Google Analytics e utilizzare il machine learning e modelli come le catene di Markov o la rete neurale per implementare questi modelli.

Raggruppamento basato sui dati per le app web
Fig. 25. Raggruppamento basato sui dati per le app web

Per facilitare questi esperimenti, siamo lieti di annunciare una nuova iniziativa che si chiama Guess.js.

Guess.js
Fig. 26. Guess.js

Guess.js è un progetto incentrato sulle esperienze utente per il web basate sui dati. Ci auguriamo che questo stimoli l'esplorazione dell'utilizzo dei dati per migliorare il rendimento sul web. È completamente open source e oggi disponibile su GitHub. È stata creata in collaborazione con la community open source da Minko Gechev, Kyle Matthews di Gatsby, Katie Hempenius e tanti altri.

Scopri Guess.js, facci sapere cosa ne pensi.

Riepilogo

I punteggi e le metriche sono utili per migliorare la velocità del web, ma sono solo il mezzo, non gli obiettivi stessi.

A tutti è capitato che le pagine vengano caricate lentamente ovunque ci si trovi, ma ora abbiamo l'opportunità di offrire agli utenti esperienze più piacevoli che si caricano molto rapidamente.

Migliorare il rendimento è un viaggio. Un sacco di piccoli cambiamenti possono portare a grandi guadagni. Utilizzando i giusti strumenti di ottimizzazione e tenendo d'occhio i report Lighthouse, puoi offrire ai tuoi utenti un'esperienza migliore e più inclusiva.

Un ringraziamento speciale a: Ward Peeters, Minko Gechev, Kyle Mathews, Katie Hempenius, Dom Farolino, Yoav Weiss, Susie Lu, Yusuke Utsunomiya, Tom Ankers, Lighthouse e Google Doodle.