A Google I/O 2018, abbiamo presentato un riepilogo di strumenti, librerie e tecniche di ottimizzazione che semplificano il miglioramento delle prestazioni web. Qui li spieghiamo utilizzando l'app The Oodles Theater. Parliamo anche dei nostri esperimenti con il caricamento predittivo e della nuova iniziativa Guess.js.
Nell'ultimo anno siamo stati piuttosto impegnati a cercare di rendere il web più veloce e performante. Ciò ha portato a 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 ogni anno. Se controlliamo lo stato del web, possiamo vedere che una pagina mediana su mobile pesa circa 1,5 MB, con la maggior parte di questi dati costituiti da JavaScript e immagini.
Le dimensioni sempre maggiori 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 complesso puzzle delle prestazioni.
La maggior parte degli utenti considera la velocità come la priorità assoluta nella gerarchia delle proprie esigenze di UX. Non è una sorpresa, perché non puoi fare molto finché una pagina non è stata caricata completamente. Non puoi derivare valore dalla pagina, non puoi ammirarne l'estetica.
Sappiamo che le prestazioni sono importanti per gli utenti, ma può anche sembrare un segreto scoprire da dove iniziare l'ottimizzazione. Fortunatamente, esistono strumenti che possono aiutarti.
Lighthouse: una base per il flusso di lavoro relativo al rendimento
Lighthouse è una parte di Chrome DevTools che ti consente di eseguire un controllo del tuo sito web e ti fornisce suggerimenti su come migliorarlo.
Di recente abbiamo lanciato una serie di nuovi controlli delle prestazioni che sono molto utili nel flusso di lavoro di sviluppo quotidiano.
Vediamo come puoi sfruttarli in un esempio pratico: L'app Oodles Theater. Si tratta di una piccola app web demo, in cui puoi provare alcuni dei nostri Doodle interattivi di Google preferiti e persino giocare a un paio di giochi.
Durante la creazione dell'app, volevamo assicurarci che fosse il più performante possibile. Il punto di partenza per l'ottimizzazione è stato un report Lighthouse.
Il rendimento iniziale della nostra app, come mostrato nel report Lighthouse, era piuttosto scarso. Su una rete 3G, l'utente doveva attendere 15 secondi per la prima visualizzazione significativa o per l'interattività dell'app. Lighthouse ha evidenziato una serie di problemi con il nostro sito e il punteggio di rendimento complessivo di 23 lo rifletteva esattamente.
La pagina pesava circa 3,4 MB, quindi dovevamo assolutamente ridurre le dimensioni.
È iniziata così la nostra prima sfida di rendimento: trovare elementi che possiamo rimuovere facilmente senza influire sull'esperienza complessiva.
Opportunità di ottimizzazione del rendimento
Rimuovere le risorse non necessarie
Ci sono alcune cose ovvie che possono essere rimosse in sicurezza: spazi bianchi e commenti.
Lighthouse evidenzia questa opportunità nel controllo CSS e JavaScript non compressi. Utilizzavamo webpack per il nostro processo di build, 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 compilazione tu utilizzi.
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 supporta questa funzionalità al giorno d'oggi.
Utilizzavamo Firebase Hosting per ospitare il nostro codice e Firebase attiva la compressione gzip per impostazione predefinita, quindi, grazie al semplice fatto di ospitare il nostro codice su una CDN ragionevole, abbiamo ottenuto questo vantaggio senza costi.
Sebbene gzip sia un metodo di compressione molto diffuso, anche altri meccanismi come Zopfli e Brotli stanno guadagnando terreno. Brotli è supportato dalla maggior parte dei browser e puoi utilizzare un binario per precomprimere gli asset prima di inviarli al server.
Utilizza policy della cache efficaci
Il passaggio successivo è stato quello di assicurarci di non inviare risorse due volte, se non necessario.
Il controllo Norme di memorizzazione nella cache inefficienti in Lighthouse ci ha aiutato a capire che potevamo ottimizzare le nostre strategie di memorizzazione nella cache per raggiungere esattamente questo obiettivo. Impostando un'intestazione di scadenza max-age nel nostro server, ci siamo assicurati che in una visita ripetuta l'utente possa riutilizzare le risorse che ha scaricato in precedenza.
Idealmente, dovresti mirare a 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 la riconvalida efficiente delle risorse aggiornate.
Rimuovi il codice inutilizzato
Finora abbiamo rimosso le parti più ovvie del download non necessario, ma cosa dire di quelle meno ovvie? Ad esempio, il codice inutilizzato.
A volte includiamo nelle nostre app codice che non è realmente necessario. Ciò accade soprattutto se lavori alla tua app per un periodo di tempo più lungo, il tuo team o le tue dipendenze cambiano e a volte una libreria orfana viene lasciata indietro. È esattamente quello che è successo a noi.
All'inizio utilizzavamo la libreria Material Components per prototipare rapidamente la nostra app. Nel tempo siamo passati a un aspetto più personalizzato e abbiamo dimenticato completamente 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 sia per il tempo di caricamento della tua applicazione. Nello screenshot in basso puoi vedere le due grandi strisce rosse: oltre il 95% del nostro CSS non veniva utilizzato, così come una grande quantità di JavaScript.
Lighthouse ha rilevato questo problema anche nel controllo delle regole CSS inutilizzate. Mostrava un potenziale risparmio di oltre 400 KB. Quindi siamo tornati al nostro codice e abbiamo rimosso sia la parte JavaScript che quella CSS di quella libreria.
In questo modo, il nostro bundle CSS è stato ridotto di 20 volte, il che è un ottimo risultato per un commit di sole due righe.
Ovviamente, il nostro punteggio di rendimento è aumentato e anche il Time to Interactive è migliorato molto.
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 prestare attenzione a potenziali regressioni.
Il nostro codice non è stato utilizzato nel 95% dei casi, ma c'è ancora un 5% da qualche parte. A quanto pare, uno dei nostri componenti utilizzava ancora gli stili di quella libreria: le piccole frecce nel cursore del doodle. Poiché era molto piccolo, abbiamo potuto reintegrare manualmente questi stili nei pulsanti.
Pertanto, se rimuovi il codice, assicurati di disporre di un flusso di lavoro di test adeguato per proteggerti da potenziali regressioni visive.
Evita payload di rete enormi
Sappiamo che le risorse di grandi dimensioni possono rallentare il caricamento delle pagine web. Possono costare denaro ai nostri utenti e avere un grande impatto sui loro piani dati, quindi è davvero importante tenerne conto.
Lighthouse è riuscito a rilevare un problema con alcuni dei nostri payload di rete utilizzando l'audit Payload di rete enorme.
Qui abbiamo visto che venivano inviati oltre 3 MB di codice, il che è molto, soprattutto sui dispositivi mobili.
Nella parte superiore di questo elenco, Lighthouse ha evidenziato che avevamo un bundle di fornitori JavaScript che conteneva 2 MB di codice non compresso. Questo è anche un problema evidenziato da webpack.
Come dice il proverbio, la richiesta più veloce è quella che non viene fatta.
Idealmente, dovresti misurare il valore di ogni singolo asset che fornisci ai tuoi utenti, misurare il rendimento di questi asset e decidere se vale la pena includerli nell'esperienza iniziale. A volte, infatti, questi asset possono essere posticipati o caricati in modo differito o elaborati durante il tempo di inattività.
Nel nostro caso, poiché abbiamo a che fare con molti bundle JavaScript, siamo stati fortunati perché la community JavaScript dispone di un ricco set di strumenti di controllo dei bundle JavaScript.
Abbiamo iniziato con webpack bundle analyzer, che ci ha informato che stavamo includendo una dipendenza chiamata unicode che era di 1,6 MB di JavaScript analizzato, quindi parecchio.
Poi siamo passati al nostro editor e, utilizzando il plug-in Import Cost per Visual Code, siamo riusciti a visualizzare il costo di ogni modulo che stavamo importando. In questo modo abbiamo potuto scoprire quale componente includeva il codice che faceva riferimento a questo modulo.
Poi siamo passati a un altro strumento, BundlePhobia. Questo strumento ti consente di inserire il nome di qualsiasi pacchetto NPM e di vedere le dimensioni stimate dopo la minificazione e la compressione gzip. Abbiamo trovato una valida alternativa al modulo slug che utilizzavamo, che pesava solo 2,2 KB, quindi l'abbiamo sostituito.
Questo ha avuto un grande impatto sul nostro rendimento. Grazie a questa modifica e alla scoperta di altre opportunità per ridurre le dimensioni del bundle JavaScript, abbiamo risparmiato 2,1 MB di codice.
Abbiamo riscontrato un miglioramento complessivo del 65% una volta preso in considerazione le dimensioni compresse e ridotte di questi bundle. Abbiamo scoperto che valeva davvero la pena farlo come processo.
Pertanto, in generale, cerca di eliminare i download non necessari nei tuoi siti e app. Fare un inventario degli asset e misurarne l'impatto sul rendimento può fare una grande differenza, quindi assicurati di eseguire regolarmente un audit degli asset.
Ridurre il tempo di avvio di JavaScript con la suddivisione del codice
Sebbene i payload di rete di grandi dimensioni possano avere un impatto significativo sulla nostra app, c'è un altro aspetto che può avere un impatto davvero grande: JavaScript.
JavaScript è la tua risorsa più costosa. Sui dispositivi mobili, se invii bundle di JavaScript di grandi dimensioni, può ritardare il momento in cui gli utenti possono interagire con i componenti dell'interfaccia utente. Ciò significa che possono toccare l'interfaccia utente senza che accada nulla di significativo. Per questo motivo è importante capire perché JavaScript costa così tanto.
Ecco come un browser elabora JavaScript.
Per prima cosa dobbiamo scaricare lo script, abbiamo un motore JavaScript che deve analizzare il codice, compilarlo ed eseguirlo.
Queste fasi non richiedono molto tempo su un dispositivo di fascia alta come un computer desktop o un laptop, forse anche uno smartphone di fascia alta. Ma su un cellulare medio questo processo può richiedere da 5 a 10 volte più tempo. Questo è ciò che ritarda l'interattività, quindi è importante per noi cercare di ridurlo.
Per aiutarti a scoprire questi problemi con la tua app, abbiamo introdotto un nuovo audit del tempo di avvio di JavaScript in Lighthouse.
Nel caso dell'app Oodle, ci ha comunicato che avevamo 1,8 secondi di tempo trascorso nell'avvio di JavaScript. Quello che succedeva era che importavamo staticamente tutte le nostre route e i nostri componenti in un unico bundle JavaScript monolitico.
Una tecnica per aggirare questo problema è l'utilizzo della suddivisione del codice.
La suddivisione del codice consiste nel dare agli utenti una fetta di JavaScript alla volta, man mano che ne hanno bisogno, invece di una pizza intera.
La suddivisione del codice può essere applicata a livello di route o di componente. Funziona perfettamente con React e React Loadable, Vue.js, Angular, Polymer, Preact e molte altre librerie.
Abbiamo incorporato la suddivisione del codice nella nostra applicazione, siamo passati dalle importazioni statiche a quelle dinamiche, il che ci ha permesso di caricare in modo asincrono il codice lazy load quando necessario.
L'impatto è stato sia la riduzione delle dimensioni dei bundle, sia la diminuzione del tempo di avvio di JavaScript. Il tempo è sceso a 0,78 secondi, rendendo l'app il 56% più veloce.
In generale, se crei un'esperienza basata su JavaScript, assicurati di inviare all'utente solo il codice di cui ha bisogno.
Sfrutta concetti come la suddivisione del codice, esplora idee come l'eliminazione del codice inutilizzato e dai un'occhiata al repository webpack-libs-optimizations per trovare alcune idee su come ridurre le dimensioni della libreria se utilizzi webpack.
Ottimizza immagini
Nell'app Oodle utilizziamo molte immagini. Purtroppo, Lighthouse non ha accolto la proposta con lo stesso entusiasmo. Infatti, non abbiamo superato tutti e tre i controlli relativi alle immagini.
Abbiamo dimenticato di ottimizzare le immagini, non le abbiamo dimensionate correttamente e potremmo ottenere qualche vantaggio dall'utilizzo di altri formati di immagine.
Abbiamo iniziato ottimizzando le nostre immagini.
Per un ciclo di ottimizzazione una tantum, puoi utilizzare 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, ti assicuri che le immagini aggiunte in futuro vengano ottimizzate automaticamente. Alcune CDN, ad esempio Akamai o soluzioni di terze parti come Cloudinary, Fastly o Uploadcare, offrono soluzioni complete di ottimizzazione delle immagini, quindi puoi anche ospitare semplicemente le tue immagini su questi servizi.
Se non vuoi farlo a causa dei costi o di problemi di latenza, progetti come Thumbor o Imageflow offrono alternative self-hosted.
Il nostro PNG di sfondo è stato segnalato in webpack come grande, e giustamente. Dopo averlo dimensionato correttamente in base all'area visibile ed eseguito ImageOptim, siamo scesi a 100 KB, il che è accettabile.
Ripetendo questa operazione per più immagini sul nostro sito, siamo riusciti a ridurre notevolmente il peso complessivo della pagina.
Utilizzare il formato giusto per i contenuti animati
Le GIF possono essere molto costose. Sorprendentemente, il formato GIF non è mai stato pensato come piattaforma di animazione. Pertanto, il passaggio a un formato video più adatto ti offre un notevole risparmio in termini di dimensioni del 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, troppo per qualsiasi sito web ragionevole, quindi lo abbiamo trasformato in un elemento video con due file di origine: un MP4 e un WebM per una maggiore compatibilità con i browser.
Abbiamo utilizzato lo strumento FFmpeg per convertire la GIF animata nel file MP4. Il formato WebM offre un risparmio ancora maggiore: l'API ImageOptim può eseguire questa conversione per te.
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 peso complessivo. In questo modo siamo scesi a circa 1 MB.
Tuttavia, 1 MB è una risorsa di grandi dimensioni da inviare, soprattutto per un utente con una larghezza di banda limitata. Fortunatamente abbiamo potuto utilizzare l'API Effective Type per capire che la larghezza di banda è lenta e inviare invece un JPEG molto più piccolo.
Questa interfaccia utilizza i valori di tempo di andata e ritorno effettivo e di interruzione per stimare il tipo di rete utilizzato dall'utente. Restituisce semplicemente una stringa: slow 2G, 2G, 3G o 4G. A seconda di questo valore, se l'utente utilizza una connessione inferiore a 4G, potremmo sostituire l'elemento video con l'immagine.
if (navigator.connection.effectiveType) { ... }
L'esperienza viene leggermente ridotta, ma almeno il sito è utilizzabile con una connessione lenta.
Caricamento lento delle immagini fuori schermo
Spesso caroselli, slider o pagine molto lunghe caricano immagini, anche se l'utente non può vederle subito sulla pagina.
Lighthouse segnalerà questo comportamento nel controllo delle immagini fuori schermo e potrai vederlo di persona nel pannello di rete di DevTools. Se vedi molte immagini in arrivo mentre solo poche sono visibili nella pagina, significa che potresti prendere in considerazione il caricamento differito.
Il caricamento differito non è ancora supportato in modo nativo nel browser, pertanto dobbiamo utilizzare JavaScript per aggiungere questa funzionalità. Abbiamo utilizzato la libreria Lazysizes per aggiungere il comportamento di caricamento differito 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"/>
Lazysizes è intelligente perché non solo tiene traccia delle modifiche alla visibilità dell'elemento, ma
precarica in modo proattivo gli elementi vicini alla visualizzazione per un'esperienza utente ottimale.
Offre anche un'integrazione facoltativa di IntersectionObserver, che ti consente di eseguire ricerche di visibilità molto
efficienti.
Dopo questa modifica, le nostre immagini vengono recuperate su richiesta. Se vuoi approfondire l'argomento, consulta images.guide, una risorsa molto utile e completa.
Aiutare il browser a fornire in anticipo le risorse critiche
Non tutti i byte inviati al browser hanno lo stesso grado di importanza e il browser lo sa. Molti browser hanno euristiche per decidere cosa recuperare per primo. A volte recuperano i CSS prima delle immagini o degli script.
Una cosa che potrebbe essere utile è che noi, in qualità di autori della pagina, comunichiamo al browser cosa
è davvero importante per noi. Fortunatamente, negli ultimi due anni i fornitori di browser hanno
aggiunto una serie di funzionalità per aiutarci in questo, ad esempio
i suggerimenti per le risorse come link rel=preconnect,
preload o prefetch.
Queste funzionalità introdotte nella piattaforma web aiutano il browser a recuperare i contenuti giusti al momento giusto e possono essere un po' più efficienti di alcuni approcci personalizzati di caricamento basati sulla logica che vengono eseguiti utilizzando script.
Vediamo come Lighthouse ci guida effettivamente verso l'utilizzo efficace di alcune di queste funzionalità.
La prima cosa che Lighthouse ci dice di fare è evitare più round trip costosi verso qualsiasi origine.
Nel caso dell'app Oodle, utilizziamo molto Google Fonts. Ogni volta che inserisci un foglio di stile di Google Fonts nella tua pagina, vengono connessi fino a due sottodomini. E Lighthouse ci dice che se riuscissimo a riscaldare la connessione, potremmo risparmiare fino a 300 millisecondi nel tempo di connessione iniziale.
Sfruttando il preconnect di link rel, possiamo mascherare in modo efficace la latenza della connessione.
Soprattutto con Google Fonts, dove il CSS dei caratteri è ospitato su googleapis.com e le risorse dei caratteri sono ospitate su Gstatic, questo può avere un impatto molto significativo. Abbiamo quindi applicato questa ottimizzazione e abbiamo ridotto i tempi di qualche centinaio di millisecondi.
La seconda cosa che suggerisce Lighthouse è di precaricare le richieste chiave.
<link rel=preload> è molto potente: comunica al browser che è necessaria una risorsa
nell'ambito della navigazione corrente e tenta di farla recuperare al browser il prima possibile.
Lighthouse ci dice che dovremmo precaricare le risorse dei caratteri web chiave, perché ne stiamo caricando due.
Il precaricamento in un carattere web ha questo aspetto: specificando rel=preload, passi as con
il tipo di carattere, quindi specifichi il tipo di carattere che stai cercando di caricare, ad esempio woff2.
L'impatto che può avere sulla tua pagina è piuttosto evidente.
Normalmente, senza utilizzare il precaricamento di link, se i caratteri web sono fondamentali per la tua pagina, il browser deve prima recuperare l'HTML, analizzare il CSS e, molto più avanti, recuperare i caratteri web.
Utilizzando il precaricamento di link rel, non appena il browser ha analizzato il codice HTML, può iniziare a recuperare i caratteri web molto prima. Nel caso della nostra app, questo ha permesso di ridurre di un secondo il tempo necessario per il rendering del testo utilizzando i nostri web font.
Ora, se vuoi provare a precaricare i caratteri utilizzando Google Fonts, non è così semplice. C'è un problema.
Gli URL di Google Fonts che specifichiamo nei nostri caratteri nei nostri fogli di stile sono qualcosa che il team di Google Fonts aggiorna abbastanza regolarmente. Questi URL possono scadere o essere aggiornati a intervalli regolari, pertanto, se vuoi avere il controllo completo sull'esperienza di caricamento dei caratteri, ti consigliamo di eseguire l'autohosting dei caratteri web. Può essere molto utile perché ti consente di accedere a elementi come il precaricamento del link rel.
Nel nostro caso, lo strumento Google Web Fonts Helper si è rivelato molto utile per aiutarci a mettere offline alcuni di questi web font e configurarli localmente, quindi dai un'occhiata a questo strumento.
Che tu stia utilizzando i caratteri web come parte delle risorse critiche o che si tratti di JavaScript, prova ad aiutare il browser a fornire le risorse critiche il prima possibile.
Sperimentale: suggerimenti di priorità
Oggi abbiamo qualcosa di speciale da condividere con te. Oltre a funzionalità come i suggerimenti per le risorse e il precaricamento, abbiamo lavorato a una nuova funzionalità sperimentale del browser che chiamiamo suggerimenti per la priorità.
Si tratta di una nuova funzionalità che consente di suggerire al browser l'importanza di una risorsa. Espone un nuovo attributo, importance, con i valori low, high o auto.
Ciò ci consente di comunicare la riduzione della priorità delle risorse meno importanti, come stili, immagini o chiamate API di recupero non critici, per ridurre la contesa. Possiamo anche aumentare la priorità di elementi più importanti, come le immagini hero.
Nel caso della nostra app Oodle, questo ha portato a un punto pratico in cui potevamo ottimizzare.
Prima di aggiungere il caricamento differito alle nostre immagini, il browser recuperava tutte le immagini del carosello dei doodle all'inizio del carosello con una priorità elevata. Purtroppo, le immagini al centro del carosello erano le più importanti per l'utente. Abbiamo impostato l'importanza delle immagini di sfondo su un valore molto basso e quelle in primo piano su un valore molto alto. In questo modo abbiamo ottenuto un impatto di due secondi sulla rete 3G lenta e sulla velocità con cui siamo riusciti a recuperare e visualizzare il rendering di queste immagini. Quindi un'esperienza positiva.
Ci auguriamo di rendere disponibile questa funzionalità su Canary tra qualche settimana, quindi non perderti gli aggiornamenti.
Avere una strategia di caricamento dei caratteri web
La tipografia è fondamentale per un buon design e, se utilizzi i caratteri web, l'ideale è non bloccare il rendering del testo e sicuramente non mostrare testo invisibile.
Ora lo evidenziamo in Lighthouse con il controllo Evita testo invisibile durante il caricamento dei caratteri web.
Se carichi i caratteri web utilizzando un blocco font-face, consenti al browser di decidere cosa fare se il recupero del carattere web richiede molto tempo. Alcuni browser attenderanno fino a tre secondi prima di ripristinare un carattere di sistema e alla fine lo sostituiranno con il carattere una volta scaricato.
Stiamo cercando di evitare questo testo invisibile, quindi in questo caso non avremmo potuto vedere i doodle classici di questa settimana se il carattere web avesse richiesto troppo tempo. Fortunatamente, con una nuova funzionalità chiamata
font-display, hai molto più controllo su questa procedura.
@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 o sostituiti i caratteri web in base al tempo necessario per lo scambio.
In questo caso utilizziamo lo scambio di visualizzazione dei caratteri. Swap assegna al carattere un periodo di blocco di zero secondi e un periodo di swap infinito. Ciò significa che il browser disegnerà il testo quasi immediatamente con un carattere di riserva se il caricamento del carattere richiede un po' di tempo. e lo sostituirà non appena il carattere sarà disponibile.
Nel caso della nostra app, questo è stato fantastico perché ci ha permesso di visualizzare un testo significativo fin da subito e di passare al carattere web una volta pronto.
In generale, se utilizzi i caratteri web, come fa una grande percentuale del web, devi avere una buona strategia di caricamento dei caratteri web.
Esistono molte funzionalità della piattaforma web che puoi utilizzare per ottimizzare l'esperienza di caricamento dei caratteri, ma ti consiglio anche di dare un'occhiata al repository Web Font Recipes di Zach Leatherman, perché è davvero fantastico.
Ridurre gli script di blocco del rendering
Ci sono altre parti della nostra applicazione che potremmo inserire prima nella catena di download per fornire almeno un'esperienza utente di base un po' prima.
Nella striscia della sequenza temporale di Lighthouse puoi notare che durante i primi secondi, quando tutte le risorse vengono caricate, l'utente non può vedere alcun contenuto.
Il download e l'elaborazione dei fogli di stile esterni impediscono al nostro processo di rendering di fare progressi.
Possiamo provare a ottimizzare il percorso di rendering critico fornendo alcuni stili un po' prima.
Se estraiamo gli stili responsabili di questo rendering iniziale e li incorporiamo nel nostro HTML, il browser è in grado di eseguirne il rendering immediatamente senza attendere l'arrivo dei fogli di stile esterni.
Nel nostro caso, abbiamo utilizzato un modulo NPM chiamato Critical per incorporare i nostri contenuti critici in index.html durante un passaggio di compilazione.
Anche se questo modulo ha fatto la maggior parte del lavoro per noi, è stato comunque un po' difficile farlo funzionare senza problemi su diversi percorsi.
Se non fai attenzione o la struttura del tuo sito è molto complessa, potrebbe essere molto difficile introdurre questo tipo di pattern se non hai pianificato l'architettura app shell fin dall'inizio.
Ecco perché è così importante prendere in considerazione le prestazioni fin dall'inizio. Se non progetti per il rendimento fin dall'inizio, è molto probabile che incontrerai problemi in un secondo momento.
Alla fine il nostro rischio ha dato i suoi frutti, siamo riusciti a farla funzionare e l'app ha iniziato a pubblicare contenuti molto prima, migliorando significativamente il tempo di caricamento iniziale.
Il risultato
Questo è un lungo elenco di ottimizzazioni delle prestazioni che abbiamo applicato al nostro sito. Diamo un'occhiata al risultato. Ecco come è stata caricata la nostra app su un dispositivo mobile medio su una rete 3G, prima e dopo l'ottimizzazione.
Il punteggio Lighthouse relativo alle prestazioni è aumentato da 23 a 91. Si tratta di un buon progresso in termini di velocità. Tutte le modifiche sono state apportate grazie al controllo e al rispetto continui del report Lighthouse. Se vuoi scoprire come abbiamo implementato tecnicamente tutti i miglioramenti, dai un'occhiata al nostro repository, in particolare alle PR che sono state inserite.
Rendimento predittivo: esperienze utente basate sui dati
Riteniamo che il machine learning rappresenti un'opportunità entusiasmante per il futuro in molti settori. Un'idea che speriamo possa stimolare una maggiore sperimentazione in futuro è che i dati reali possono davvero guidare le esperienze utente che stiamo creando.
Oggi prendiamo molte decisioni arbitrarie su ciò che l'utente potrebbe volere o di cui potrebbe avere bisogno e, di conseguenza, su ciò che vale la pena precaricare o prememorizzare nella cache. Se indoviniamo, possiamo dare la priorità a una piccola quantità di risorse, ma è molto difficile estenderla a tutto il sito web.
Oggi disponiamo di dati che ci consentono di ottimizzare meglio le campagne. Utilizzando l'API di reporting di Google Analytics possiamo esaminare la pagina successiva più visitata e le percentuali di uscita per qualsiasi URL del nostro sito e quindi trarre conclusioni sulle risorse a cui dare la priorità.
Se combiniamo questo modello con un buon modello di probabilità, evitiamo di sprecare i dati dei nostri utenti precaricando in modo aggressivo i contenuti. Possiamo sfruttare questi dati di Google Analytics e utilizzare il machine learning e modelli come le catene di Markov o le reti neurali per implementare questi modelli.
Per facilitare questi esperimenti, siamo felici di annunciare una nuova iniziativa che abbiamo chiamato Guess.js.
Guess.js è un progetto incentrato su esperienze utente basate sui dati per il web. Ci auguriamo che vi ispiri a esplorare l'utilizzo dei dati per migliorare il rendimento del web e andare oltre. È tutto open source e disponibile su GitHub oggi. È stato creato in collaborazione con la community open source da Minko Gechev, Kyle Matthews di Gatsby, Katie Hempenius e molti altri.
Dai un'occhiata a Guess.js e facci sapere cosa ne pensi.
Riepilogo
I punteggi e le metriche sono utili per migliorare la velocità del web, ma sono solo i mezzi, non gli obiettivi stessi.
A tutti è capitato di riscontrare caricamenti lenti delle pagine in mobilità, ma ora abbiamo l'opportunità di offrire ai nostri utenti esperienze più piacevoli che si caricano molto rapidamente.
Migliorare il rendimento è un percorso. Molti piccoli cambiamenti possono portare a grandi risultati. Utilizzando gli strumenti di ottimizzazione giusti e tenendo d'occhio i report Lighthouse, puoi offrire un'esperienza migliore e più inclusiva ai tuoi utenti.
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.