Elenco di controllo delle prestazioni front-end 2021 (PDF, pagine Apple, MS Word)

Pubblicato: 2022-03-10
Riassunto veloce ↬ Facciamo il 2021… veloce! Un elenco di controllo annuale delle prestazioni front-end (disponibile in formato PDF, Apple Pages, MS Word), con tutto ciò che devi sapere per creare esperienze veloci sul Web oggi, dalle metriche agli strumenti e alle tecniche di front-end. Aggiornato dal 2016. Ah, puoi anche ricevere utili suggerimenti per il front-end nella nostra newsletter via e-mail.

Le prestazioni sul Web sono una bestia ingannevole, vero? Come facciamo a sapere effettivamente a che punto siamo in termini di prestazioni e quali sono esattamente i nostri colli di bottiglia in termini di prestazioni? JavaScript è costoso, consegna dei caratteri web lenta, immagini pesanti o rendering lento? Abbiamo ottimizzato abbastanza con tree-shaking, scope hoisting, code-splitting e tutti i modelli di caricamento fantasiosi con osservatore di intersezioni, idratazione progressiva, suggerimenti per i clienti, HTTP/3, addetti ai servizi e - oh mio - lavoratori edge? E, soprattutto, da dove iniziamo a migliorare le prestazioni e come stabiliamo una cultura delle prestazioni a lungo termine?

In passato, le prestazioni erano spesso un semplice ripensamento . Spesso rinviato fino alla fine del progetto, si riduce a minimizzazione, concatenazione, ottimizzazione delle risorse e potenzialmente alcune regolazioni fini sul file di config del server. Guardando indietro ora, le cose sembrano essere cambiate in modo abbastanza significativo.

Le prestazioni non sono solo una questione tecnica: influiscono su tutto, dall'accessibilità all'usabilità, all'ottimizzazione dei motori di ricerca e, quando le integrano nel flusso di lavoro, le decisioni di progettazione devono essere informate dalle loro implicazioni sulle prestazioni. Le prestazioni devono essere misurate, monitorate e perfezionate continuamente e la crescente complessità del Web pone nuove sfide che rendono difficile tenere traccia delle metriche, poiché i dati variano in modo significativo a seconda del dispositivo, del browser, del protocollo, del tipo di rete e della latenza ( CDN, ISP, cache, proxy, firewall, bilanciatori di carico e server svolgono tutti un ruolo nelle prestazioni).

Quindi, se creassimo una panoramica di tutte le cose che dobbiamo tenere a mente quando si migliorano le prestazioni, dall'inizio del progetto fino al rilascio finale del sito Web, come sarebbe? Di seguito troverai un elenco di controllo delle prestazioni front-end (si spera imparziale e obiettivo) per il 2021 : una panoramica aggiornata dei problemi che potresti dover considerare per assicurarti che i tuoi tempi di risposta siano rapidi, l'interazione dell'utente sia fluida e i tuoi siti no drenare la larghezza di banda dell'utente.

Sommario

  • Tutto su pagine separate
  • Prepararsi: pianificazione e metriche
    Cultura delle prestazioni, Core Web Vitals, profili delle prestazioni, CrUX, Lighthouse, FID, TTI, CLS, dispositivi.
  • Stabilire obiettivi realistici
    Budget prestazionali, obiettivi prestazionali, framework RAIL, budget 170KB/30KB.
  • Definire l'ambiente
    Scelta di un framework, costo delle prestazioni di base, Webpack, dipendenze, CDN, architettura front-end, CSR, SSR, CSR + SSR, rendering statico, prerendering, pattern PRPL.
  • Ottimizzazioni degli asset
    Brotli, AVIF, WebP, immagini reattive, AV1, caricamento multimediale adattivo, compressione video, font web, font Google.
  • Costruisci ottimizzazioni
    Moduli JavaScript, pattern modulo/nomodulo, tree-shaking, code-splitting, scope-hoisting, Webpack, pubblicazione differenziale, web worker, WebAssembly, bundle JavaScript, React, SPA, idratazione parziale, importazione su interazione, terze parti, cache.
  • Ottimizzazioni di consegna
    Caricamento lento, osservatore di intersezione, differire il rendering e la decodifica, CSS critico, streaming, suggerimenti sulle risorse, turni di layout, addetto ai servizi.
  • Rete, HTTP/2, HTTP/3
    Pinzatura OCSP, certificati EV/DV, packaging, IPv6, QUIC, HTTP/3.
  • Test e monitoraggio
    Flusso di lavoro di controllo, browser proxy, pagina 404, richieste di consenso ai cookie GDPR, CSS di diagnostica delle prestazioni, accessibilità.
  • Vittorie veloci
  • Scarica la lista di controllo (PDF, Apple Pages, MS Word)
  • Si parte!

(Puoi anche scaricare il PDF della checklist (166 KB) o scaricare il file modificabile di Apple Pages (275 KB) o il file .docx (151 KB). Buona ottimizzazione, a tutti!)

Prepararsi: pianificazione e metriche

Le micro-ottimizzazioni sono ottime per mantenere le prestazioni in carreggiata, ma è fondamentale avere in mente obiettivi chiaramente definiti, obiettivi misurabili che influenzerebbero qualsiasi decisione presa durante il processo. Esistono un paio di modelli diversi e quelli discussi di seguito sono piuttosto supponenti: assicurati solo di stabilire le tue priorità all'inizio.

  1. Stabilire una cultura della performance.
    In molte organizzazioni, gli sviluppatori front-end sanno esattamente quali sono i problemi sottostanti comuni e quali strategie dovrebbero essere utilizzate per risolverli. Tuttavia, fintanto che non esiste un'approvazione consolidata della cultura della performance, ogni decisione si trasformerà in un campo di battaglia di dipartimenti, suddividendo l'organizzazione in silos. Hai bisogno di un coinvolgimento degli stakeholder aziendali e, per ottenerlo, devi stabilire un case study o un proof of concept su come la velocità, in particolare i Core Web Vitals di cui parleremo in dettaglio più avanti, avvantaggia le metriche e gli indicatori chiave di prestazione ( KPI ) a cui tengono.

    Ad esempio, per rendere le prestazioni più tangibili, è possibile esporre l'impatto sulle prestazioni dei ricavi mostrando la correlazione tra il tasso di conversione e il tempo di caricamento dell'applicazione, nonché le prestazioni di rendering. Oppure la velocità di scansione del bot di ricerca (PDF, pagine 27–50).

    Senza un forte allineamento tra i team di sviluppo/design e business/marketing, le prestazioni non saranno sostenute a lungo termine. Studia i reclami comuni che arrivano al servizio clienti e al team di vendita, studia l'analisi per frequenze di rimbalzo elevate e cali di conversione. Scopri come migliorare le prestazioni può aiutare ad alleviare alcuni di questi problemi comuni. Modifica l'argomento in base al gruppo di stakeholder con cui stai parlando.

    Esegui esperimenti sulle prestazioni e misura i risultati, sia su dispositivi mobili che desktop (ad esempio con Google Analytics). Ti aiuterà a creare un case study personalizzato con dati reali. Inoltre, l'utilizzo dei dati di casi di studio ed esperimenti pubblicati su WPO Stats aiuterà ad aumentare la sensibilità per le aziende sul motivo per cui le prestazioni sono importanti e quale impatto ha sull'esperienza utente e sulle metriche aziendali. Tuttavia, affermare che le prestazioni contano da sole non è sufficiente: devi anche stabilire alcuni obiettivi misurabili e tracciabili e osservarli nel tempo.

    Come arrivare là? Nel suo discorso su Building Performance for the Long Term, Allison McKnight condivide un caso di studio completo su come ha contribuito a stabilire una cultura della performance su Etsy (diapositive). Più recentemente, Tammy Everts ha parlato delle abitudini dei team di prestazioni altamente efficaci nelle organizzazioni di piccole e grandi dimensioni.

    Durante queste conversazioni nelle organizzazioni, è importante tenere a mente che, proprio come l'UX è uno spettro di esperienze, le prestazioni web sono una distribuzione. Come ha osservato Karolina Szczur, "aspettarsi che un singolo numero sia in grado di fornire una valutazione a cui aspirare è un'ipotesi errata". Quindi gli obiettivi di prestazione devono essere dettagliati, tracciabili e tangibili.

Sui dispositivi mobili, per sessione, gli utenti che hanno riscontrato tempi di caricamento rapidi generano il 17% di entrate in più rispetto alla media
Sui dispositivi mobili, per sessione, gli utenti che hanno riscontrato tempi di caricamento rapidi generano il 17% di entrate in più rispetto alla media. (Impatto delle prestazioni Web, tramite Addy Osmani)
Aspettarsi che un singolo numero sia in grado di fornire una valutazione a cui aspirare è un'ipotesi errata
Aspettarsi che un singolo numero sia in grado di fornire una valutazione a cui aspirare è un'ipotesi errata. (Credito immagine: Performance è una distribuzione tramite Karolina Czczur)
  1. Obiettivo: essere almeno il 20% più veloce del tuo concorrente più veloce.
    Secondo la ricerca psicologica, se vuoi che gli utenti sentano che il tuo sito web è più veloce del sito web della concorrenza, devi essere almeno il 20% più veloce. Studia i tuoi principali concorrenti, raccogli metriche su come si comportano su dispositivi mobili e desktop e imposta soglie che ti aiuterebbero a superarli. Tuttavia, per ottenere risultati e obiettivi accurati, assicurati di avere prima un quadro completo dell'esperienza dei tuoi utenti studiando le tue analisi. È quindi possibile imitare l'esperienza del 90° percentile per i test.

    Per avere una buona prima impressione delle prestazioni dei tuoi concorrenti, puoi utilizzare Chrome UX Report ( CrUX , un set di dati RUM già pronto, video introduttivo di Ilya Grigorik e guida dettagliata di Rick Viscomi) o Treo, uno strumento di monitoraggio RUM che è alimentato da Chrome UX Report. I dati vengono raccolti dagli utenti del browser Chrome, quindi i rapporti saranno specifici di Chrome, ma ti forniranno una distribuzione abbastanza completa delle prestazioni, soprattutto i punteggi di Core Web Vitals, su un'ampia gamma di visitatori. Si noti che i nuovi dataset CrUX vengono rilasciati il ​​secondo martedì di ogni mese .

    In alternativa puoi anche utilizzare:

    • Strumento di confronto dei rapporti sull'esperienza utente di Chrome di Addy Osmani,
    • Speed ​​Scorecard (fornisce anche uno strumento per la stima dell'impatto sulle entrate),
    • Confronto del test dell'esperienza utente reale o
    • SiteSpeed ​​CI (basato su test sintetici).

    Nota : se utilizzi Page Speed ​​Insights o l'API Page Speed ​​Insights (no, non è deprecato!), puoi ottenere i dati sulle prestazioni di CrUX per pagine specifiche anziché solo per gli aggregati. Questi dati possono essere molto più utili per impostare obiettivi di rendimento per risorse come "pagina di destinazione" o "scheda di prodotto". E se stai usando CI per testare i budget, devi assicurarti che il tuo ambiente testato corrisponda a CrUX se hai usato CrUX per impostare l'obiettivo ( grazie Patrick Meenan! ).

    Se hai bisogno di aiuto per mostrare il ragionamento alla base della definizione delle priorità della velocità, o se desideri visualizzare il decadimento del tasso di conversione o l'aumento della frequenza di rimbalzo con prestazioni più lente, o forse avresti bisogno di sostenere una soluzione RUM nella tua organizzazione, Sergey Chernyshev ha creato un UX Speed ​​Calculator, uno strumento open source che ti aiuta a simulare i dati e visualizzarli per guidare il tuo punto.

    CrUX genera una panoramica delle distribuzioni delle prestazioni nel tempo, con il traffico raccolto dagli utenti di Google Chrome
    CrUX genera una panoramica delle distribuzioni delle prestazioni nel tempo, con il traffico raccolto dagli utenti di Google Chrome. Puoi crearne uno personalizzato su Chrome UX Dashboard. (Grande anteprima)
    Proprio quando hai bisogno di fare un caso per le prestazioni per guidare il tuo punto: UX Speed ​​Calculator visualizza l'impatto delle prestazioni su frequenze di rimbalzo, conversione e entrate totali, sulla base di dati reali
    Proprio quando hai bisogno di dimostrare che le prestazioni guidino il tuo punto di vista: UX Speed ​​Calculator visualizza l'impatto delle prestazioni su frequenze di rimbalzo, conversione e entrate totali, in base a dati reali. (Grande anteprima)

    A volte potresti voler andare un po' più a fondo, combinando i dati provenienti da CrUX con qualsiasi altro dato che hai già per capire rapidamente dove si trovano i rallentamenti, i punti ciechi e le inefficienze, per i tuoi concorrenti o per il tuo progetto. Nel suo lavoro, Harry Roberts ha utilizzato un foglio di calcolo della topografia della velocità del sito che utilizza per suddividere le prestazioni in base ai tipi di pagina chiave e tenere traccia delle diverse metriche chiave su di esse. Puoi scaricare il foglio di lavoro come Fogli Google, Excel, documento OpenOffice o CSV.

    Topografia della velocità del sito, con metriche chiave rappresentate per le pagine chiave del sito
    Topografia della velocità del sito, con metriche chiave rappresentate per le pagine chiave del sito. (Grande anteprima)

    E se vuoi andare fino in fondo , puoi eseguire un audit delle prestazioni di Lighthouse su ogni pagina di un sito (tramite Lightouse Parade), con un output salvato come CSV. Ciò ti aiuterà a identificare quali pagine (o tipi di pagine) specifici dei tuoi concorrenti hanno prestazioni peggiori o migliori e su cosa potresti voler concentrare i tuoi sforzi. (Per il tuo sito, probabilmente è meglio inviare dati a un endpoint di analisi!).

    Con Lighthouse Parade, puoi eseguire un audit delle prestazioni di Lighthouse su ogni pagina di un sito, con un output salvato come CSV
    Con Lighthouse Parade, puoi eseguire un controllo delle prestazioni di Lighthouse su ogni pagina di un sito, con un output salvato come CSV. (Grande anteprima)

    Raccogli dati, imposta un foglio di lavoro, riduci il 20% e imposta i tuoi obiettivi ( budget di rendimento ) in questo modo. Ora hai qualcosa di misurabile con cui testare. Se stai tenendo a mente il budget e stai cercando di spedire solo il carico utile minimo per ottenere un rapido time-to-interactive, allora sei su una strada ragionevole.

    Hai bisogno di risorse per iniziare?

    • Addy Osmani ha scritto un articolo molto dettagliato su come avviare il budgeting delle prestazioni, come quantificare l'impatto delle nuove funzionalità e da dove iniziare quando si supera il budget.
    • La guida di Lara Hogan su come affrontare i progetti con un budget di prestazioni può fornire utili suggerimenti ai designer.
    • Harry Roberts ha pubblicato una guida sull'impostazione di un foglio Google per visualizzare l'impatto degli script di terze parti sulle prestazioni, utilizzando Request Map,
    • Il calcolatore del budget delle prestazioni di Jonathan Fielding, il calcolatore del budget perf di Katie Hempenius e le calorie del browser possono aiutare nella creazione di budget (grazie a Karolina Szczur per l'avviso).
    • In molte aziende, i budget delle prestazioni non dovrebbero essere ambiziosi, ma piuttosto pragmatici, fungendo da segno di attesa per evitare di scivolare oltre un certo punto. In tal caso, potresti scegliere come soglia il tuo peggior punto dati nelle ultime due settimane e prenderlo da lì. Budget delle prestazioni, ti mostra pragmaticamente una strategia per raggiungerlo.
    • Inoltre, rendi visibili sia il budget delle prestazioni che le prestazioni attuali impostando dashboard con grafici che riportano le dimensioni delle build. Esistono molti strumenti che ti consentono di raggiungere questo obiettivo: dashboard SiteSpeed.io (open source), SpeedCurve e Calibre sono solo alcuni di questi e puoi trovare più strumenti su perf.rocks.
    Browser Calories ti aiuta a impostare un budget di rendimento e misurare se una pagina supera questi numeri o meno,
    Browser Calories ti aiuta a impostare un budget di rendimento e misurare se una pagina supera questi numeri o meno. (Grande anteprima)

    Una volta stabilito un budget, incorporalo nel processo di creazione con Webpack Performance Hints e Bundlesize, Lighthouse CI, PWMetrics o Sitespeed CI per applicare i budget alle richieste pull e fornire una cronologia dei punteggi nei commenti PR.

    Per esporre i budget delle prestazioni all'intero team, integra i budget delle prestazioni in Lighthouse tramite Lightwallet o usa LHCI Action per una rapida integrazione di Github Actions. E se hai bisogno di qualcosa di personalizzato, puoi utilizzare webpagetest-charts-api, un'API di endpoint per creare grafici dai risultati di WebPagetest.

    Tuttavia, la consapevolezza delle prestazioni non dovrebbe venire solo dai budget delle prestazioni. Proprio come Pinterest, potresti creare una regola eslint personalizzata che non consenta l'importazione da file e directory noti per essere molto dipendenti e gonfiare il pacchetto. Imposta un elenco di pacchetti "sicuri" che possono essere condivisi con l'intero team.

    Inoltre, pensa alle attività critiche dei clienti che sono più vantaggiose per la tua attività. Studiare, discutere e definire soglie di tempo accettabili per le azioni critiche e stabilire tempi utente "UX ready" approvati dall'intera organizzazione. In molti casi, i percorsi degli utenti toccheranno il lavoro di molti reparti diversi, quindi l'allineamento in termini di tempi accettabili aiuterà a supportare o prevenire le discussioni sulle prestazioni lungo la strada. Assicurati che i costi aggiuntivi delle risorse e delle funzionalità aggiunte siano visibili e compresi.

    Allinea gli sforzi in termini di prestazioni con altre iniziative tecnologiche, che vanno dalle nuove funzionalità del prodotto in fase di creazione al refactoring fino al raggiungimento di un nuovo pubblico globale. Quindi, ogni volta che si verifica una conversazione su un ulteriore sviluppo, anche le prestazioni fanno parte di quella conversazione. È molto più facile raggiungere gli obiettivi di prestazioni quando la base di codice è nuova o è solo in fase di refactoring.

    Inoltre, come suggerito da Patrick Meenan, vale la pena pianificare una sequenza di caricamento e dei compromessi durante il processo di progettazione. Se dai la priorità in anticipo a quali parti sono più critiche e definisci l'ordine in cui dovrebbero apparire, saprai anche cosa può essere ritardato. Idealmente, quell'ordine rifletterà anche la sequenza delle tue importazioni CSS e JavaScript, quindi gestirle durante il processo di compilazione sarà più semplice. Inoltre, considera quale dovrebbe essere l'esperienza visiva negli stati "intermedi", mentre la pagina viene caricata (ad esempio quando i caratteri web non sono ancora stati caricati).

    Una volta che hai stabilito una forte cultura delle prestazioni nella tua organizzazione, punta a essere il 20% più veloce di te stesso per mantenere intatte le priorità con il passare del tempo ( grazie, Guy Podjarny! ). Ma tieni conto dei diversi tipi e comportamenti di utilizzo dei tuoi clienti (che Tobias Baldauf ha chiamato cadenza e coorti), insieme al traffico dei bot e agli effetti della stagionalità.

    Pianificazione, pianificazione, pianificazione. Potrebbe essere allettante entrare presto in alcune rapide ottimizzazioni dei "frutti bassi" - e potrebbe essere una buona strategia per vittorie rapide - ma sarà molto difficile mantenere le prestazioni una priorità senza pianificare e impostare una compagnia realistica - obiettivi di performance su misura.

Treo Sites fornisce analisi della concorrenza basate su dati del mondo reale
Treo fornisce analisi della concorrenza basate su dati del mondo reale. (Grande anteprima)
Nuove metriche sono arrivate in Lighthouse v6 all'inizio del 2020
Nuove metriche sono arrivate in Lighthouse v6 all'inizio del 2020. (Anteprima ampia)
  1. Scegli le metriche giuste.
    Non tutte le metriche sono ugualmente importanti. Studia quali metriche contano di più per la tua applicazione: di solito, sarà definita dalla velocità con cui puoi iniziare a eseguire il rendering dei pixel più importanti della tua interfaccia e dalla velocità con cui puoi fornire la reattività all'input per questi pixel renderizzati. Questa conoscenza ti darà il miglior obiettivo di ottimizzazione per gli sforzi in corso. Alla fine, non sono gli eventi di caricamento o i tempi di risposta del server a definire l'esperienza, ma la percezione di quanto sia scattante l'interfaccia.

    Cosa significa? Piuttosto che concentrarti sul tempo di caricamento della pagina intera (tramite i tempi onLoad e DOMContentLoaded , ad esempio), dai la priorità al caricamento della pagina come percepito dai tuoi clienti. Ciò significa concentrarsi su un insieme leggermente diverso di metriche. In effetti, scegliere la metrica giusta è un processo senza vincitori evidenti.

    Sulla base della ricerca di Tim Kadlec e delle note di Marcos Iglesias nel suo intervento, le metriche tradizionali potrebbero essere raggruppate in pochi set. Di solito, avremo bisogno di tutti loro per avere un quadro completo delle prestazioni e nel tuo caso particolare alcuni di essi saranno più importanti di altri.

    • Le metriche basate sulla quantità misurano il numero di richieste, il peso e un punteggio di prestazione. Buono per generare allarmi e monitorare i cambiamenti nel tempo, non così buono per comprendere l'esperienza dell'utente.
    • Le metriche di traguardo utilizzano gli stati durante la durata del processo di caricamento, ad esempio Time To First Byte e Time To Interactive . Buono per descrivere l'esperienza dell'utente e il monitoraggio, non così buono per sapere cosa succede tra le pietre miliari.
    • Le metriche di rendering forniscono una stima della velocità di rendering del contenuto (ad es. Tempo di avvio del rendering , Indice di velocità ). Buono per misurare e modificare le prestazioni di rendering, ma non così buono per misurare quando vengono visualizzati contenuti importanti e con cui è possibile interagire.
    • Le metriche personalizzate misurano un particolare evento personalizzato per l'utente, ad esempio Time To First Tweet di Twitter e PinnerWaitTime di Pinterest. Buono per descrivere con precisione l'esperienza dell'utente, non così buono per ridimensionare le metriche e confrontarlo con i concorrenti.

    Per completare il quadro, di solito cerchiamo metriche utili tra tutti questi gruppi. Di solito, quelli più specifici e rilevanti sono:

    • Time to Interactive (TTI)
      Il punto in cui il layout si è stabilizzato , i webfont chiave sono visibili e il thread principale è abbastanza disponibile per gestire l'input dell'utente, in pratica il contrassegno temporale in cui un utente può interagire con l'interfaccia utente. Le metriche chiave per capire quanta attesa deve subire un utente per utilizzare il sito senza ritardi. Boris Schapira ha scritto un post dettagliato su come misurare il TTI in modo affidabile.
    • First Input Delay (FID) o Reattività di input
      Il momento in cui un utente interagisce per la prima volta con il tuo sito al momento in cui il browser è effettivamente in grado di rispondere a tale interazione. Completa molto bene TTI in quanto descrive la parte mancante dell'immagine: cosa succede quando un utente interagisce effettivamente con il sito. Inteso solo come metrica RUM. C'è una libreria JavaScript per misurare il FID nel browser.
    • La più grande vernice contenta (LCP)
      Contrassegna il punto nella sequenza temporale di caricamento della pagina in cui è probabile che il contenuto importante della pagina sia stato caricato. Il presupposto è che l'elemento più importante della pagina sia quello più grande visibile nel viewport dell'utente. Se gli elementi sono renderizzati sia above che below the fold, solo la parte visibile è considerata rilevante.
    • Tempo di blocco totale ( TBT )
      Una metrica che aiuta a quantificare la gravità di quanto una pagina non sia interattiva prima che diventi interattiva in modo affidabile (ovvero, il thread principale è stato privo di attività che superano i 50 ms ( attività lunghe ) per almeno 5 secondi). La metrica misura la quantità di tempo totale tra il primo disegno e Time to Interactive (TTI) in cui il thread principale è stato bloccato per un tempo sufficientemente lungo da impedire la reattività dell'input. Non c'è da stupirsi, quindi, che un TBT basso sia un buon indicatore di buone prestazioni. (grazie, Artem, Phil)
    • Spostamento cumulativo del layout ( CLS )
      La metrica evidenzia la frequenza con cui gli utenti subiscono cambiamenti di layout imprevisti ( ridistribuzioni ) quando accedono al sito. Esamina gli elementi instabili e il loro impatto sull'esperienza complessiva. Più basso è il punteggio, meglio è.
    • Indice di velocità
      Misura la velocità con cui i contenuti della pagina vengono popolati visivamente; più basso è il punteggio, meglio è. Il punteggio dell'indice di velocità viene calcolato in base alla velocità di avanzamento visivo , ma è semplicemente un valore calcolato. È anche sensibile alle dimensioni del viewport, quindi è necessario definire una gamma di configurazioni di test che corrispondano al pubblico di destinazione. Nota che sta diventando meno importante con LCP che sta diventando una metrica più rilevante ( grazie, Boris, Artem! ).
    • Tempo CPU speso
      Una metrica che mostra la frequenza e la durata del blocco del thread principale, lavorando su pittura, rendering, scripting e caricamento. Il tempo di CPU elevato è un chiaro indicatore di un'esperienza janky , ovvero quando l'utente sperimenta un notevole ritardo tra la propria azione e una risposta. Con WebPageTest, puoi selezionare "Capture Dev Tools Timeline" nella scheda "Chrome" per esporre l'interruzione del thread principale mentre viene eseguito su qualsiasi dispositivo utilizzando WebPageTest.
    • Costi della CPU a livello di componente
      Proprio come per il tempo impiegato dalla CPU , questa metrica, proposta da Stoyan Stefanov, esplora l' impatto di JavaScript sulla CPU . L'idea è di utilizzare il conteggio delle istruzioni della CPU per componente per comprenderne l'impatto sull'esperienza complessiva, in isolamento. Potrebbe essere implementato utilizzando Burattinaio e Chrome.
    • Indice di frustrazione
      Mentre molti parametri descritti sopra spiegano quando si verifica un evento particolare, FrustrationIndex di Tim Vereecke esamina i divari tra i parametri invece di esaminarli individualmente. Esamina le pietre miliari chiave percepite dall'utente finale, come il titolo è visibile, il primo contenuto è visibile, visivamente pronto e la pagina sembra pronta e calcola un punteggio che indica il livello di frustrazione durante il caricamento di una pagina. Maggiore è il divario, maggiore è la possibilità che un utente venga frustrato. Potenzialmente un buon KPI per l'esperienza dell'utente. Tim ha pubblicato un post dettagliato su FrustrationIndex e su come funziona.
    • Impatto sul peso dell'annuncio
      Se il tuo sito dipende dalle entrate generate dalla pubblicità, è utile monitorare il peso del codice relativo agli annunci. Lo script di Paddy Ganti costruisce due URL (uno normale e uno che blocca gli annunci), richiede la generazione di un confronto video tramite WebPageTest e segnala un delta.
    • Metriche di deviazione
      Come notato dagli ingegneri di Wikipedia, i dati su quanta varianza esiste nei tuoi risultati potrebbero informarti sull'affidabilità dei tuoi strumenti e quanta attenzione dovresti prestare a deviazioni e outler. Una grande varianza è un indicatore delle regolazioni necessarie nell'impostazione. Aiuta anche a capire se alcune pagine sono più difficili da misurare in modo affidabile, ad esempio a causa di script di terze parti che causano variazioni significative. Potrebbe anche essere una buona idea tenere traccia della versione del browser per comprendere i picchi di prestazioni quando viene lanciata una nuova versione del browser.
    • Metriche personalizzate
      Le metriche personalizzate sono definite dalle esigenze aziendali e dall'esperienza del cliente. Richiede di identificare pixel importanti , script critici , CSS necessari e risorse pertinenti e misurare la velocità con cui vengono consegnati all'utente. Per quello, puoi monitorare i tempi di rendering dell'eroe o utilizzare l'API delle prestazioni, contrassegnando timestamp particolari per eventi importanti per la tua attività. Inoltre, puoi raccogliere metriche personalizzate con WebPagetest eseguendo JavaScript arbitrario alla fine di un test.

    Nota che il First Significato Paint (FMP) non appare nella panoramica sopra. Un tempo forniva un'idea della velocità con cui il server emette i dati. L'FMP lungo di solito indicava che JavaScript bloccava il thread principale, ma potrebbe essere correlato anche a problemi di back-end/server. Tuttavia, la metrica è stata deprecata di recente in quanto non sembra essere accurata in circa il 20% dei casi. È stato effettivamente sostituito con LCP che è sia più affidabile che più facile da ragionare. Non è più supportato in Lighthouse. Ricontrolla le ultime metriche e consigli sulle prestazioni incentrati sull'utente solo per assicurarti di essere sulla pagina sicura ( grazie, Patrick Meenan ).

    Steve Souders ha una spiegazione dettagliata di molti di questi parametri. È importante notare che mentre il Time-To-Interactive viene misurato eseguendo controlli automatizzati nel cosiddetto ambiente di laboratorio , First Input Delay rappresenta l'esperienza utente effettiva , con gli utenti effettivi che subiscono un notevole ritardo. In generale, è probabilmente una buona idea misurare e monitorare sempre entrambi.

    A seconda del contesto dell'applicazione, le metriche preferite potrebbero differire: ad es. per l'interfaccia utente di Netflix TV, la reattività dell'input chiave, l'utilizzo della memoria e il TTI sono più importanti e per Wikipedia, le prime/ultime modifiche visive e le metriche del tempo impiegato dalla CPU sono più importanti.

    Nota : sia FID che TTI non tengono conto del comportamento di scorrimento; lo scorrimento può avvenire in modo indipendente poiché è fuori dal thread principale, quindi per molti siti di consumo di contenuti queste metriche potrebbero essere molto meno importanti ( grazie, Patrick! ).

Le metriche delle prestazioni incentrate sull'utente forniscono una visione migliore dell'esperienza utente effettiva
Le metriche delle prestazioni incentrate sull'utente forniscono una visione migliore dell'esperienza utente effettiva. First Input Delay (FID) è una nuova metrica che cerca di ottenere proprio questo. (Grande anteprima)
Nuovi Core Web Vitals in una panoramica, LCP < 2,5 s, FID < 100 ms, CLS < 0,1
Nuovi Core Web Vitals in una panoramica, LCP < 2,5 s, FID < 100 ms, CLS < 0,1. (Core Web Vitals, tramite Addy Osmani)
  1. Misurare e ottimizzare i Core Web Vitals .
    Per molto tempo, le metriche delle prestazioni sono state piuttosto tecniche, incentrate sulla visione ingegneristica della velocità di risposta dei server e della velocità di caricamento dei browser. Le metriche sono cambiate nel corso degli anni, cercando di trovare un modo per catturare l'esperienza utente effettiva , piuttosto che i tempi del server. A maggio 2020, Google ha annunciato Core Web Vitals, una serie di nuove metriche delle prestazioni incentrate sull'utente, ciascuna delle quali rappresenta un aspetto distinto dell'esperienza dell'utente.

    Per ciascuno di essi, Google consiglia una serie di obiettivi di velocità accettabili. Almeno il 75% di tutte le visualizzazioni di pagina deve superare l' intervallo Buono per superare questa valutazione. Queste metriche hanno rapidamente guadagnato terreno e, con i Core Web Vitals che sono diventati indicatori di ranking per la Ricerca Google a maggio 2021 ( aggiornamento dell'algoritmo di ranking di Page Experience ), molte aziende hanno rivolto la loro attenzione ai punteggi delle prestazioni.

    Analizziamo ciascuno dei Core Web Vitals, uno per uno, insieme a tecniche e strumenti utili per ottimizzare le tue esperienze tenendo conto di queste metriche. (Vale la pena notare che ti ritroverai con punteggi migliori di Core Web Vitals seguendo un consiglio generale in questo articolo.)

    • Più grande Contentful Paint ( LCP ) < 2,5 sec.
      Misura il caricamento di una pagina e segnala il tempo di rendering dell'immagine o del blocco di testo più grande visibile all'interno del viewport. Pertanto, LCP è influenzato da tutto ciò che sta rinviando il rendering di informazioni importanti, che si tratti di tempi di risposta del server lenti, blocco dei CSS, JavaScript in corso (di prima parte o di terze parti), caricamento di font Web, costose operazioni di rendering o pittura, pigrizia -immagini caricate, schermate dello scheletro o rendering lato client.

      Per una buona esperienza, LCP dovrebbe verificarsi entro 2,5 secondi dal primo caricamento della pagina. Ciò significa che dobbiamo rendere la prima parte visibile della pagina il prima possibile. Ciò richiederà CSS critici personalizzati per ogni modello, orchestrando l'ordine di <head> e precaricando le risorse critiche (le tratteremo più avanti).

      Il motivo principale per un punteggio LCP basso sono solitamente le immagini. Fornire un LCP in meno di 2,5 secondi su Fast 3G — ospitato su un server ben ottimizzato, tutto statico senza rendering lato client e con un'immagine proveniente da un CDN di immagini dedicato — significa che la dimensione teorica massima dell'immagine è di soli 144 KB circa . Ecco perché le immagini reattive sono importanti, così come il precaricamento delle immagini critiche in anticipo (con preload ).

      Suggerimento rapido : per scoprire cosa è considerato LCP su una pagina, in DevTools puoi passare il mouse sopra il badge LCP sotto "Tempi" nel Performance Panel ( grazie, Tim Kadlec !).

    • Ritardo primo ingresso ( FID ) < 100 ms.
      Misura la reattività dell'interfaccia utente, ovvero per quanto tempo il browser è stato impegnato con altre attività prima che potesse reagire a un evento di input dell'utente discreto come un tocco o un clic. È progettato per catturare i ritardi risultanti dall'occupazione del thread principale, soprattutto durante il caricamento della pagina.

      L'obiettivo è rimanere entro 50–100 ms per ogni interazione. Per arrivarci, dobbiamo identificare attività lunghe (blocca il thread principale per >50 ms) e suddividerle, suddividere il codice in più blocchi, ridurre il tempo di esecuzione di JavaScript, ottimizzare il recupero dei dati, rinviare l'esecuzione di script di terze parti , sposta JavaScript nel thread in background con i Web worker e utilizza l'idratazione progressiva per ridurre i costi di reidratazione nelle SPA.

      Suggerimento rapido : in generale, una strategia affidabile per ottenere un punteggio FID migliore consiste nel ridurre al minimo il lavoro sul thread principale suddividendo i pacchetti più grandi in pacchetti più piccoli e servendo ciò di cui l'utente ha bisogno quando ne ha bisogno, in modo che le interazioni dell'utente non vengano ritardate . Ne tratteremo di più in dettaglio di seguito.

    • Spostamento cumulativo del layout ( CLS ) < 0,1.
      Misura la stabilità visiva dell'interfaccia utente per garantire interazioni fluide e naturali, ovvero la somma totale di tutti i singoli punteggi di spostamento del layout per ogni spostamento imprevisto del layout che si verifica durante la vita della pagina. Un cambiamento di layout individuale si verifica ogni volta che un elemento già visibile cambia la sua posizione nella pagina. Viene valutato in base alle dimensioni del contenuto e alla distanza percorsa.

      Quindi ogni volta che compare un cambiamento, ad esempio quando i font di fallback e i web font hanno metriche dei font differenti, o annunci, incorporamenti o iframe che arrivano in ritardo, o le dimensioni dell'immagine/video non sono riservate, o il CSS in ritardo impone ridisegni o le modifiche vengono iniettate da late JavaScript: ha un impatto sul punteggio CLS. Il valore consigliato per una buona esperienza è un CLS < 0,1.

    Vale la pena notare che i Core Web Vitals dovrebbero evolversi nel tempo, con un ciclo annuale prevedibile . Per l'aggiornamento del primo anno, potremmo aspettarci che First Contentful Paint venga promosso a Core Web Vitals, una soglia FID ridotta e un migliore supporto per le applicazioni a pagina singola. Potremmo anche vedere la risposta agli input degli utenti dopo il carico aumentare di peso, insieme a considerazioni di sicurezza, privacy e accessibilità (!).

    In relazione a Core Web Vitals, ci sono molte risorse utili e articoli che vale la pena esaminare:

    • Web Vitals Leaderboard ti consente di confrontare i tuoi punteggi con la concorrenza su dispositivi mobili, tablet, desktop e su 3G e 4G.
    • Core SERP Vitals, un'estensione di Chrome che mostra i Core Web Vitals di CrUX nei risultati di ricerca di Google.
    • Layout Shift GIF Generator che visualizza CLS con una semplice GIF (disponibile anche da riga di comando).
    • la libreria web-vitals può raccogliere e inviare Core Web Vitals a Google Analytics, Google Tag Manager o qualsiasi altro endpoint di analisi.
    • Analisi di Web Vitals con WebPageTest, in cui Patrick Meenan esplora come WebPageTest espone i dati sui Core Web Vitals.
    • Ottimizzazione con Core Web Vitals, un video di 50 minuti con Addy Osmani, in cui evidenzia come migliorare Core Web Vitals in un caso di studio di eCommerce.
    • Spostamento cumulativo del layout nella pratica e Spostamento cumulativo del layout nel mondo reale sono articoli completi di Nic Jansma, che coprono praticamente tutto su CLS e come si correla con metriche chiave come frequenza di rimbalzo, tempo di sessione o clic di rabbia.
    • Cosa forza il riflusso, con una panoramica delle proprietà o dei metodi, quando richiesto/chiamato in JavaScript, che attiverà il browser per calcolare in modo sincrono lo stile e il layout.
    • Trigger CSS mostra quali proprietà CSS attivano Layout, Paint e Composite.
    • La correzione dell'instabilità del layout è una procedura dettagliata dell'utilizzo di WebPageTest per identificare e correggere i problemi di instabilità del layout.
    • Cumulative Layout Shift, The Layout Instability Metric, un'altra guida molto dettagliata di Boris Schapira su CLS, come viene calcolato, come misurare e come ottimizzarlo.
    • How To Improvement Core Web Vitals, una guida dettagliata di Simon Hearne su ciascuna delle metriche (inclusi altri Web Vital, come FCP, TTI, TBT), quando si verificano e come vengono misurate.

    Quindi, Core Web Vitals è la metrica definitiva da seguire ? Non proprio. Sono infatti già esposti nella maggior parte delle soluzioni e piattaforme RUM, tra cui Cloudflare, Treo, SpeedCurve, Calibre, WebPageTest (già nella vista filmstrip), Newrelic, Shopify, Next.js, tutti gli strumenti di Google (PageSpeed ​​Insights, Lighthouse + CI, Search Console ecc.) e molti altri.

    Tuttavia, come spiega Katie Sylor-Miller, alcuni dei problemi principali con Core Web Vitals sono la mancanza di supporto cross-browser, non misuriamo realmente l'intero ciclo di vita dell'esperienza di un utente, inoltre è difficile correlare i cambiamenti in FID e CLS con risultati di business.

    Poiché dovremmo aspettarci un'evoluzione di Core Web Vitals, sembra ragionevole combinare sempre Web Vitals con le tue metriche personalizzate per ottenere una migliore comprensione della tua posizione in termini di prestazioni.

  2. Raccogli dati su un dispositivo rappresentativo del tuo pubblico.
    Per raccogliere dati accurati, dobbiamo scegliere accuratamente i dispositivi su cui testare. Nella maggior parte delle aziende, ciò significa esaminare le analisi e creare profili utente basati sui tipi di dispositivi più comuni. Tuttavia, spesso, l'analisi da sola non fornisce un quadro completo. Una parte significativa del pubblico di destinazione potrebbe abbandonare il sito (e non tornare indietro) solo perché la loro esperienza è troppo lenta ed è improbabile che i loro dispositivi vengano visualizzati come i dispositivi più popolari nell'analisi per questo motivo. Quindi, condurre ulteriori ricerche su dispositivi comuni nel tuo gruppo target potrebbe essere una buona idea.

    A livello globale nel 2020, secondo l'IDC, l'84,8% di tutti i telefoni cellulari spediti sono dispositivi Android. Un consumatore medio aggiorna il proprio telefono ogni 2 anni e negli Stati Uniti il ​​ciclo di sostituzione del telefono è di 33 mesi. I telefoni più venduti in media in tutto il mondo costeranno meno di $ 200.

    Un dispositivo rappresentativo, quindi, è un dispositivo Android che ha almeno 24 mesi , costa $ 200 o meno, funziona su 3G lento, 400 ms RTT e 400 kbps di trasferimento, solo per essere leggermente più pessimisti. Questo potrebbe essere molto diverso per la tua azienda, ovviamente, ma questa è un'approssimazione abbastanza vicina alla maggior parte dei clienti là fuori. In effetti, potrebbe essere una buona idea esaminare gli attuali Best Seller di Amazon per il tuo mercato di riferimento. ( Grazie a Tim Kadlec, Henri Helvetica e Alex Russell per le indicazioni! ).

    Quando crei un nuovo sito o un'app, controlla sempre prima gli attuali Best Seller di Amazon per il tuo mercato di riferimento
    Quando crei un nuovo sito o un'app, controlla sempre prima gli attuali Best Seller di Amazon per il tuo mercato di riferimento. (Grande anteprima)

    Quali dispositivi di test scegliere allora? Quelli che si adattano bene al profilo sopra delineato. È una buona opzione scegliere un Moto G4/G5 Plus leggermente più vecchio, un dispositivo Samsung di fascia media (Galaxy A50, S8), un buon dispositivo di fascia media come un Nexus 5X, Xiaomi Mi A3 o Xiaomi Redmi Note 7 e un dispositivo lento come Alcatel 1X o Cubot X19, magari in un laboratorio di dispositivi aperti. Per i test su dispositivi con accelerazione termica più lenti, potresti anche ottenere un Nexus 4, che costa solo circa $ 100.

    Inoltre, controlla i chipset utilizzati in ogni dispositivo e non sovrarappresentare un chipset : alcune generazioni di Snapdragon e Apple oltre a Rockchip di fascia bassa, Mediatek sarebbero sufficienti (grazie, Patrick!) .

    Se non hai un dispositivo a portata di mano, emula l'esperienza mobile sul desktop testando su una rete 3G ridotta (ad es. 300 ms RTT, 1,6 Mbps giù, 0,8 Mbps su) con una CPU ridotta (5 volte il rallentamento). Alla fine passa al normale 3G, al 4G lento (ad es. 170 ms RTT, 9 Mbps in basso, 9 Mbps in alto) e Wi-Fi. Per rendere più visibile l'impatto sulle prestazioni, potresti persino introdurre i martedì 2G o configurare una rete 3G/4G ridotta nel tuo ufficio per test più rapidi.

    Tieni presente che su un dispositivo mobile dovremmo aspettarci un rallentamento 4×–5× rispetto alle macchine desktop. I dispositivi mobili hanno diverse GPU, CPU, memoria e diverse caratteristiche della batteria. Ecco perché è importante avere un buon profilo di un dispositivo medio e testare sempre su un dispositivo del genere.

  3. Ti presentiamo il giorno più lento della settimana
    Ti presentiamo il giorno più lento della settimana. Facebook ha introdotto i martedì 2G per aumentare la visibilità e la sensibilità delle connessioni lente. (Fonte immagine)

    Fortunatamente, ci sono molte ottime opzioni che ti aiutano ad automatizzare la raccolta di dati e a misurare le prestazioni del tuo sito web nel tempo in base a queste metriche. Tieni presente che un buon quadro delle prestazioni copre una serie di metriche delle prestazioni, dati di laboratorio e dati sul campo:

    • Gli strumenti di test sintetici raccolgono i dati di laboratorio in un ambiente riproducibile con dispositivi e impostazioni di rete predefiniti (ad es. Lighthouse , Calibre , WebPageTest ) e
    • Gli strumenti Real User Monitoring ( RUM ) valutano continuamente le interazioni degli utenti e raccolgono dati sul campo (ad es. SpeedCurve , New Relic : gli strumenti forniscono anche test sintetici).

    Il primo è particolarmente utile durante lo sviluppo in quanto ti aiuterà a identificare, isolare e risolvere i problemi di prestazioni mentre lavori sul prodotto. Quest'ultimo è utile per la manutenzione a lungo termine in quanto ti aiuterà a comprendere i colli di bottiglia delle prestazioni mentre si verificano dal vivo, quando gli utenti accedono effettivamente al sito.

    Toccando le API RUM integrate come Navigation Timing, Resource Timing, Paint Timing, Long Tasks, ecc., gli strumenti di test sintetici e RUM insieme forniscono un quadro completo delle prestazioni della tua applicazione. Puoi usare Calibre, Treo, SpeedCurve, mPulse e Boomerang, Sitespeed.io, che sono tutte ottime opzioni per il monitoraggio delle prestazioni. Inoltre, con l'intestazione Server Timing, puoi persino monitorare le prestazioni di back-end e front-end in un unico posto.

    Nota : è sempre una scommessa più sicura scegliere dei throttling a livello di rete, esterni al browser, poiché, ad esempio, DevTools ha problemi nell'interazione con HTTP/2 push, a causa del modo in cui è implementato ( grazie, Yoav, Patrick !). Per Mac OS, possiamo usare Network Link Conditioner, per Windows Windows Traffic Shaper, per Linux netem e per FreeBSD dummynet.

    Poiché è probabile che eseguirai il test in Lighthouse, tieni presente che puoi:

    • usa Lighthouse CI per tenere traccia dei punteggi di Lighthouse nel tempo (è piuttosto impressionante),
    • esegui Lighthouse in GitHub Actions per ottenere un report Lighthouse insieme a ogni PR,
    • eseguire un audit delle prestazioni di Lighthouse su ogni pagina di un sito (tramite Lightouse Parade), con un output salvato come CSV,
    • usa il calcolatore dei punteggi del faro e i pesi metrici del faro se hai bisogno di approfondire i dettagli.
    • Lighthouse è disponibile anche per Firefox, ma sotto il cofano utilizza l'API PageSpeed ​​Insights e genera un rapporto basato su un Chrome 79 User-Agent senza testa.
Lighthouse CI è piuttosto notevole: una suite di strumenti per eseguire, salvare, recuperare e affermare continuamente i risultati di Lighthouse
Lighthouse CI è piuttosto notevole: una suite di strumenti per eseguire, salvare, recuperare e affermare continuamente i risultati di Lighthouse. (Grande anteprima)
  1. Impostare i profili "pulito" e "cliente" per il test.
    Durante l'esecuzione di test negli strumenti di monitoraggio passivo, è una strategia comune disattivare le attività antivirus e in background della CPU, rimuovere i trasferimenti di larghezza di banda in background e testare con un profilo utente pulito senza estensioni del browser per evitare risultati distorti (in Firefox e in Chrome).
    Il rapporto di DebugBear mette in evidenza le 20 estensioni più lente, inclusi gestori di password, ad-blocker e applicazioni popolari come Evernote e Grammarly
    Il rapporto di DebugBear mette in evidenza le 20 estensioni più lente, inclusi gestori di password, ad-blocker e applicazioni popolari come Evernote e Grammarly. (Grande anteprima)

    Tuttavia, è anche una buona idea studiare quali estensioni del browser utilizzano frequentemente i tuoi clienti e testare anche con profili "clienti" dedicati. In effetti, alcune estensioni potrebbero avere un profondo impatto sulle prestazioni (rapporto sul rendimento delle estensioni di Chrome 2020) sulla tua applicazione e, se i tuoi utenti le utilizzano molto, potresti voler tenerne conto in anticipo. Pertanto, i risultati del profilo "pulito" da soli sono eccessivamente ottimistici e possono essere schiacciati in scenari di vita reale.

  2. Condividi gli obiettivi di performance con i tuoi colleghi.
    Assicurati che gli obiettivi di prestazione siano familiari a tutti i membri della tua squadra per evitare malintesi su tutta la linea. Ogni decisione, che si tratti di progettazione, marketing o qualsiasi altra via di mezzo, ha implicazioni sulle prestazioni e la distribuzione di responsabilità e proprietà nell'intero team semplificherebbe le decisioni incentrate sulle prestazioni in seguito. Mappa le decisioni di progettazione rispetto al budget delle prestazioni e alle priorità definite all'inizio.

Stabilire obiettivi realistici

  1. Tempo di risposta di 100 millisecondi, 60 fps.
    Affinché un'interazione sia fluida, l'interfaccia ha 100 ms per rispondere all'input dell'utente. Non più a lungo e l'utente percepisce l'app come lenta. Il RAIL, un modello di prestazioni incentrato sull'utente, offre obiettivi sani : per consentire una risposta <100 millisecondi, la pagina deve restituire il controllo al thread principale al più tardi ogni <50 millisecondi. La latenza di input stimata ci dice se stiamo raggiungendo quella soglia e, idealmente, dovrebbe essere inferiore a 50 ms. Per i punti ad alta pressione come l'animazione, è meglio non fare nient'altro dove puoi e il minimo assoluto dove non puoi.

    RAIL, un modello di prestazioni incentrato sull'utente.
    RAIL, un modello di prestazioni incentrato sull'utente.

    Inoltre, ogni fotogramma dell'animazione dovrebbe essere completato in meno di 16 millisecondi, ottenendo così 60 fotogrammi al secondo (1 secondo ÷ 60 = 16,6 millisecondi), preferibilmente sotto i 10 millisecondi. Poiché il browser ha bisogno di tempo per dipingere il nuovo frame sullo schermo, il codice dovrebbe terminare l'esecuzione prima di raggiungere il segno di 16,6 millisecondi. Stiamo iniziando a parlare di 120 fps (ad es. gli schermi di iPad Pro funzionano a 120 Hz) e Surma ha coperto alcune soluzioni di prestazioni di rendering per 120 fps, ma probabilmente non è un obiettivo che stiamo ancora guardando.

    Sii pessimista nelle aspettative sulle prestazioni, ma sii ottimista nella progettazione dell'interfaccia e usa saggiamente il tempo di inattività (seleziona idle, idle-finché-urgente e reagisci-idle). Ovviamente, questi obiettivi si applicano alle prestazioni di runtime, piuttosto che alle prestazioni di caricamento.

  2. FID < 100 ms, LCP < 2,5 s, TTI < 5 s su 3G, budget per dimensioni file critiche < 170 KB (gzippato).
    Anche se potrebbe essere molto difficile da raggiungere, un buon obiettivo finale sarebbe Time to Interactive sotto i 5 anni e, per le visite ripetute, puntare ai minori di 2 anni (raggiungibile solo con un addetto al servizio). Puntare alla pittura di contenuto più grande di meno di 2,5 secondi e ridurre al minimo il tempo di blocco totale e lo spostamento cumulativo del layout . Un ritardo del primo ingresso accettabile è inferiore a 100 ms–70 ms. Come accennato in precedenza, stiamo considerando che la linea di base è un telefono Android da $ 200 (ad es. Moto G4) su una rete 3G lenta, emulato a 400 ms RTT e velocità di trasferimento di 400 kbps.

    Abbiamo due vincoli principali che modellano efficacemente un obiettivo ragionevole per la consegna rapida dei contenuti sul Web. Da un lato, abbiamo vincoli di recapito della rete dovuti a TCP Slow Start. I primi 14 KB dell'HTML - 10 pacchetti TCP, ciascuno da 1460 byte, per un totale di circa 14,25 KB, anche se da non prendere alla lettera - è il pezzo di carico utile più critico e l'unica parte del budget che può essere consegnata nel primo roundtrip ( che è tutto ciò che ottieni in 1 secondo a 400 ms RTT a causa degli orari di sveglia dei dispositivi mobili).

    Rete di browser ad alte prestazioni di Ilya Grigorik
    Con le connessioni TCP, iniziamo con una piccola finestra di congestione e la raddoppiamo per ogni andata e ritorno. Nel primo viaggio di andata e ritorno, possiamo contenere 14 KB. Da: Rete di browser ad alte prestazioni di Ilya Grigorik. (Grande anteprima)

    ( Nota : poiché TCP generalmente sottoutilizza la connessione di rete in misura significativa, Google ha sviluppato TCP Bottleneck Bandwidth e RRT ( BBR ), un algoritmo di controllo del flusso TCP controllato dal ritardo TCP. Progettato per il Web moderno, risponde alla congestione effettiva, invece della perdita di pacchetti come fa TCP, è significativamente più veloce, con un throughput più elevato e una latenza inferiore e l'algoritmo funziona in modo diverso ( grazie, Victor, Barry! ).

    D'altra parte, abbiamo vincoli hardware su memoria e CPU a causa dell'analisi di JavaScript e dei tempi di esecuzione (ne parleremo in dettaglio più avanti). Per raggiungere gli obiettivi indicati nel primo paragrafo, dobbiamo considerare il budget critico delle dimensioni dei file per JavaScript. Le opinioni variano su quale dovrebbe essere quel budget (e dipende fortemente dalla natura del tuo progetto), ma un budget di 170 KB JavaScript già compresso richiederebbe fino a 1 secondo per analizzare e compilare su un telefono di fascia media. Supponendo che 170 KB si espandano a 3 volte quella dimensione quando decompresso (0,7 MB), quella potrebbe già essere la campana a morto di un'esperienza utente "decente" su un Moto G4/G5 Plus.

    Nel caso del sito Web di Wikipedia, nel 2020, a livello globale, l'esecuzione del codice è diventata più veloce del 19% per gli utenti di Wikipedia. Quindi, se le tue metriche sulle prestazioni web anno dopo anno rimangono stabili, di solito è un segnale di avvertimento poiché stai effettivamente regredendo mentre l'ambiente continua a migliorare (dettagli in un post sul blog di Gilles Dubuc).

    Se vuoi rivolgerti a mercati in crescita come il Sud-est asiatico, l'Africa o l'India, dovrai considerare una serie di vincoli molto diversi. Addy Osmani copre i principali vincoli dei feature phone, come pochi dispositivi a basso costo e di alta qualità, l'indisponibilità di reti di alta qualità e dati mobili costosi, insieme al budget PRPL-30 e alle linee guida di sviluppo per questi ambienti.

    Secondo Addy Osmani, anche una dimensione consigliata per i percorsi con caricamento lento è inferiore a 35 KB
    Secondo Addy Osmani, anche una dimensione consigliata per i percorsi con caricamento lento è inferiore a 35 KB. (Grande anteprima)
    Addy Osmani suggerisce un budget per le prestazioni PRPL-30 (30 KB compressi con gzip + bundle iniziale ridotto al minimo) se si rivolge a un feature phone
    Addy Osmani suggerisce un budget per le prestazioni PRPL-30 (30 KB compresso con gzip + bundle iniziale ridotto al minimo) se si rivolge a un feature phone. (Grande anteprima)

    In effetti, Alex Russell di Google consiglia di puntare a 130–170 KB compressi con gzip come limite superiore ragionevole. Negli scenari del mondo reale, la maggior parte dei prodotti non è nemmeno vicina: una dimensione media del pacchetto oggi è di circa 452 KB, con un aumento del 53,6% rispetto all'inizio del 2015. Su un dispositivo mobile di classe media, ciò rappresenta 12-20 secondi per Time -To-Interattivo .

    Geekbench benchmark delle prestazioni della CPU per gli smartphone più venduti a livello globale nel 2019. JavaScript sottolinea le prestazioni single-core ed è vincolato alla CPU
    Geekbench benchmark delle prestazioni della CPU per gli smartphone più venduti a livello globale nel 2019. JavaScript sottolinea le prestazioni single-core (ricorda, è intrinsecamente più single-thread rispetto al resto della piattaforma Web) ed è vincolato alla CPU. Dall'articolo di Addy "Caricamento veloce di pagine Web su un telefono con funzionalità da $ 20". (Grande anteprima)

    Potremmo anche andare oltre il budget per le dimensioni del pacchetto. Ad esempio, potremmo impostare i budget delle prestazioni in base alle attività del thread principale del browser, ad esempio il tempo di disegno prima dell'inizio del rendering, o rintracciare i problemi di CPU front-end. Strumenti come Calibre, SpeedCurve e Bundlesize possono aiutarti a tenere sotto controllo i tuoi budget e possono essere integrati nel tuo processo di creazione.

    Infine, un budget di rendimento probabilmente non dovrebbe essere un valore fisso . A seconda della connessione di rete, i budget delle prestazioni dovrebbero adattarsi, ma il carico utile su una connessione più lenta è molto più "costoso", indipendentemente da come vengono utilizzati.

    Nota : potrebbe sembrare strano impostare budget così rigidi in tempi di HTTP/2 diffuso, imminenti 5G e HTTP/3, telefoni cellulari in rapida evoluzione e fiorenti SPA. Tuttavia, sembrano ragionevoli quando affrontiamo la natura imprevedibile della rete e dell'hardware, compreso qualsiasi cosa, dalle reti congestionate all'infrastruttura in lento sviluppo, ai limiti di dati, ai browser proxy, alla modalità di salvataggio dei dati e alle tariffe di roaming subdole.

Da "Fast By Default: Modern Loading Best Practices" di Addy Osmani
Da Fast By Default: Best practice di caricamento moderne di Addy Osmani (diapositiva 19)
I budget delle prestazioni dovrebbero adattarsi a seconda delle condizioni di rete per un dispositivo mobile medio
I budget delle prestazioni dovrebbero adattarsi a seconda delle condizioni di rete per un dispositivo mobile medio. (Fonte immagine: Katie Hempenius) (Anteprima grande)

Definire l'ambiente

  1. Scegli e configura i tuoi strumenti di costruzione.
    Non prestare troppa attenzione a ciò che è apparentemente cool in questi giorni. Attenersi al proprio ambiente per la costruzione, che si tratti di Grunt, Gulp, Webpack, Parcel o una combinazione di strumenti. Finché ottieni i risultati di cui hai bisogno e non hai problemi a mantenere il tuo processo di creazione, stai andando bene.

    Tra gli strumenti di build, Rollup continua a guadagnare terreno, così come Snowpack, ma Webpack sembra essere il più consolidato, con letteralmente centinaia di plugin disponibili per ottimizzare le dimensioni delle tue build. Fai attenzione alla Roadmap Webpack 2021.

    Una delle strategie più importanti apparse di recente è il blocco granulare con Webpack in Next.js e Gatsby per ridurre al minimo il codice duplicato. Per impostazione predefinita, i moduli che non sono condivisi in ogni punto di ingresso possono essere richiesti per i percorsi che non lo utilizzano. Questo finisce per diventare un sovraccarico poiché viene scaricato più codice del necessario. Con il chunking granulare in Next.js, possiamo utilizzare un file manifest di build lato server per determinare quali blocchi emessi vengono utilizzati da diversi punti di ingresso.

    Per ridurre il codice duplicato nei progetti Webpack, possiamo utilizzare il chunking granulare, abilitato in Next.js e Gatsby per impostazione predefinita
    Per ridurre il codice duplicato nei progetti Webpack, possiamo utilizzare il chunking granulare, abilitato in Next.js e Gatsby per impostazione predefinita. Credito immagine: Addy Osmani. (Grande anteprima)

    Con SplitChunksPlugin, vengono creati più blocchi divisi in base a una serie di condizioni per impedire il recupero di codice duplicato su più percorsi. Ciò migliora il tempo di caricamento della pagina e la memorizzazione nella cache durante le navigazioni. Spedito in Next.js 9.2 e in Gatsby v2.20.7.

    Tuttavia, iniziare con Webpack può essere difficile. Quindi, se vuoi tuffarti in Webpack, ci sono alcune ottime risorse là fuori:

    • La documentazione di Webpack, ovviamente, è un buon punto di partenza, così come Webpack — The Confusing Bits di Raja Rao e An Annotated Webpack Config di Andrew Welch.
    • Sean Larkin ha un corso gratuito su Webpack: The Core Concepts e Jeffrey Way ha rilasciato un fantastico corso gratuito su Webpack per tutti. Entrambi sono ottime introduzioni per immergersi in Webpack.
    • Webpack Fundamentals è un corso molto completo di 4 ore con Sean Larkin, pubblicato da FrontendMasters.
    • Gli esempi di Webpack hanno centinaia di configurazioni Webpack pronte per l'uso, suddivise per argomento e scopo. Bonus: esiste anche un configuratore di configurazione Webpack che genera un file di configurazione di base.
    • awesome-webpack è un elenco curato di utili risorse Webpack, librerie e strumenti, inclusi articoli, video, corsi, libri ed esempi per progetti Angular, React e indipendenti dal framework.
    • Il viaggio verso la creazione rapida di risorse di produzione con Webpack è il case study di Etsy su come il team è passato dall'utilizzo di un sistema di compilazione JavaScript basato su RequireJS all'utilizzo di Webpack e su come ha ottimizzato le proprie build, gestendo in media oltre 13.200 risorse in 4 minuti .
    • I suggerimenti per le prestazioni di Webpack sono una miniera d'oro di Ivan Akulov, con molti suggerimenti incentrati sulle prestazioni, inclusi quelli incentrati specificamente su Webpack.
    • awesome-webpack-perf è un repository GitHub miniera d'oro con utili strumenti Webpack e plug-in per le prestazioni. Mantenuto anche da Ivan Akulov.
Una visualizzazione del viaggio di Etsy verso la produzione veloce si costruisce con Webpack
Il viaggio di Etsy verso una produzione veloce si costruisce con Webpack (tramite Addy Osmani) (Anteprima grande)
  1. Usa il miglioramento progressivo come impostazione predefinita.
    Tuttavia, dopo tutti questi anni, mantenere il miglioramento progressivo come principio guida dell'architettura e della distribuzione front-end è una scommessa sicura. Progetta e costruisci prima l'esperienza di base, quindi migliora l'esperienza con funzionalità avanzate per browser capaci, creando esperienze resilienti. Se il tuo sito Web funziona velocemente su una macchina lenta con uno schermo scadente in un browser scadente su una rete non ottimale, funzionerà più velocemente solo su una macchina veloce con un buon browser su una rete decente.

    In effetti, con il servizio di moduli adattivi, sembra che stiamo portando il miglioramento progressivo a un altro livello, offrendo esperienze di base "lite" ai dispositivi di fascia bassa e migliorando con funzionalità più sofisticate per i dispositivi di fascia alta. È improbabile che il miglioramento progressivo svanisca presto.

  2. Scegli una linea di base di prestazioni forti.
    Con così tante incognite che incidono sul caricamento: rete, limitazione termica, rimozione della cache, script di terze parti, modelli di blocco del parser, I/O del disco, latenza IPC, estensioni installate, software antivirus e firewall, attività CPU in background, vincoli hardware e di memoria, differenze nella memorizzazione nella cache L2/L3, RTTS: JavaScript ha il costo più pesante dell'esperienza, accanto ai caratteri Web che bloccano il rendering per impostazione predefinita e alle immagini che spesso consumano troppa memoria. Con i colli di bottiglia delle prestazioni che si spostano dal server al client, come sviluppatori dobbiamo considerare tutte queste incognite in modo molto più dettagliato.

    Con un budget di 170 KB che contiene già il percorso critico HTML/CSS/JavaScript, router, gestione dello stato, utilità, framework e logica dell'applicazione, dobbiamo esaminare a fondo il costo di trasferimento di rete, il tempo di analisi/compilazione e il costo di runtime del quadro di nostra scelta. Fortunatamente, negli ultimi anni abbiamo assistito a un enorme miglioramento nella velocità con cui i browser possono analizzare e compilare gli script. Tuttavia, l'esecuzione di JavaScript è ancora il collo di bottiglia principale, quindi prestare molta attenzione al tempo di esecuzione degli script e alla rete può avere un impatto.

    Tim Kadlec ha condotto una fantastica ricerca sulle prestazioni dei framework moderni e le ha riassunte nell'articolo "I framework JavaScript hanno un costo". Parliamo spesso dell'impatto dei framework standalone, ma come osserva Tim, in pratica non è raro avere più framework in uso . Forse una versione precedente di jQuery che viene lentamente migrata a un framework moderno, insieme ad alcune applicazioni legacy che utilizzano una versione precedente di Angular. Quindi è più ragionevole esplorare il costo cumulativo dei byte JavaScript e del tempo di esecuzione della CPU che può facilmente rendere le esperienze utente a malapena utilizzabili, anche su dispositivi di fascia alta.

    In generale, i framework moderni non danno la priorità ai dispositivi meno potenti , quindi le esperienze su un telefono e su desktop saranno spesso notevolmente diverse in termini di prestazioni. Secondo la ricerca, i siti con React o Angular trascorrono più tempo sulla CPU rispetto ad altri (il che ovviamente non significa necessariamente che React sia più costoso sulla CPU di Vue.js).

    Secondo Tim, una cosa è ovvia: "se stai utilizzando un framework per costruire il tuo sito, stai facendo un compromesso in termini di prestazioni iniziali , anche nel migliore degli scenari".

Il costo dei framework, il tempo della CPU JavaScript: i siti SPA funzionano male
Il costo dei framework, JavaScript byes: i siti SPA (ancora) funzionano male
Tempo CPU relativo allo scripting per dispositivi mobili e byte JavaScript per dispositivi desktopv. In generale, i siti con React o Angular trascorrono più tempo sulla CPU rispetto ad altri. Ma dipende da come costruisci il sito. Ricerca di Tim Kadlec. (Grande anteprima)
  1. Valuta framework e dipendenze.
    Ora, non tutti i progetti necessitano di un framework e non tutte le pagine di un'applicazione a pagina singola devono caricare un framework. Nel caso di Netflix, "la rimozione di React, diverse librerie e il codice dell'app corrispondente dal lato client ha ridotto la quantità totale di JavaScript di oltre 200 KB, causando una riduzione di oltre il 50% del tempo di interattività di Netflix per la home page disconnessa ." Il team ha quindi utilizzato il tempo trascorso dagli utenti sulla pagina di destinazione per precaricare React per le pagine successive su cui è probabile che gli utenti atterrano (continua a leggere per i dettagli).

    E se rimuovessi del tutto un framework esistente su pagine critiche? Con Gatsby, puoi controllare gatsby-plugin-no-javascript che rimuove tutti i file JavaScript creati da Gatsby dai file HTML statici. Su Vercel, puoi anche consentire la disabilitazione di JavaScript runtime in produzione per determinate pagine (sperimentale).

    Una volta scelto un framework, lo utilizzeremo per almeno alcuni anni, quindi se dobbiamo utilizzarne uno, dobbiamo assicurarci che la nostra scelta sia informata e ben ponderata, e questo vale soprattutto per le metriche chiave delle prestazioni che cura.

    I dati mostrano che, per impostazione predefinita, i framework sono piuttosto costosi: il 58,6% delle pagine React spedisce oltre 1 MB di JavaScript e il 36% dei caricamenti di pagine Vue.js ha un First Contentful Paint di <1,5s. Secondo uno studio di Ankur Sethi, "la tua applicazione React non si caricherà mai più velocemente di circa 1,1 secondi su un telefono medio in India, non importa quanto la ottimizzi. La tua app Angular impiegherà sempre almeno 2,7 secondi per avviarsi. Il gli utenti della tua app Vue dovranno attendere almeno 1 secondo prima di poter iniziare a utilizzarla." Potresti comunque non rivolgerti all'India come mercato principale, ma gli utenti che accedono al tuo sito con condizioni di rete non ottimali avranno un'esperienza simile.

    Ovviamente è possibile realizzare SPA veloci, ma non sono veloci, quindi dobbiamo tenere conto del tempo e degli sforzi necessari per realizzarle e mantenerle veloci. Probabilmente sarà più facile scegliendo all'inizio un costo di base delle prestazioni leggero.

    Allora come scegliamo un framework ? È buona norma considerare almeno il costo totale sulla dimensione + i tempi di esecuzione iniziali prima di scegliere un'opzione; opzioni leggere come Preact, Inferno, Vue, Svelte, Alpine o Polymer possono portare a termine il lavoro perfettamente. La dimensione della tua linea di base definirà i vincoli per il codice della tua applicazione.

    Come notato da Seb Markbage, un buon modo per misurare i costi di avvio per i framework è prima eseguire il rendering di una vista, quindi eliminarla e quindi renderizzare di nuovo in quanto può dirti come scala il framework. Il primo rendering tende a riscaldare un mucchio di codice compilato in modo pigro, di cui un albero più grande può trarre vantaggio quando viene ridimensionato. Il secondo rendering è fondamentalmente un'emulazione di come il riutilizzo del codice in una pagina influisce sulle caratteristiche delle prestazioni man mano che la pagina cresce in complessità.

    Potresti arrivare fino a valutare i tuoi candidati (o qualsiasi libreria JavaScript in generale) sul sistema di punteggio in scala a 12 punti di Sacha Greif esplorando funzionalità, accessibilità, stabilità, prestazioni, ecosistema di pacchetti , comunità, curva di apprendimento, documentazione, strumenti, track record , team, compatibilità, sicurezza per esempio.

    Perf Track tiene traccia delle prestazioni del framework su larga scala
    Perf Track tiene traccia delle prestazioni del framework su larga scala. (Grande anteprima)

    Puoi anche fare affidamento sui dati raccolti sul Web per un periodo di tempo più lungo. Ad esempio, Perf Track tiene traccia delle prestazioni del framework su larga scala, mostrando i punteggi dei Core Web Vitals aggregati all'origine per i siti Web creati in Angular, React, Vue, Polymer, Preact, Ember, Svelte e AMP. Puoi anche specificare e confrontare i siti Web creati con Gatsby, Next.js o Create React App, nonché i siti Web creati con Nuxt.js (Vue) o Sapper (Svelte).

    Un buon punto di partenza è scegliere un buon stack predefinito per la tua applicazione. Gatsby (React), Next.js (React), Vuepress (Vue), Preact CLI e PWA Starter Kit forniscono impostazioni predefinite ragionevoli per un rapido caricamento immediato sull'hardware mobile medio. ​​Inoltre, dai un'occhiata alla guida alle prestazioni specifiche del framework web.dev per React e Angular ( grazie, Phillip! ).

    E forse potresti adottare un approccio leggermente più rinfrescante alla creazione di applicazioni a pagina singola: Turbolinks, una libreria JavaScript da 15 KB che utilizza HTML anziché JSON per il rendering delle visualizzazioni. Quindi, quando segui un link, Turbolinks recupera automaticamente la pagina, scambia il suo <body> e unisce il suo <head> , il tutto senza incorrere nel costo di un caricamento completo della pagina. Puoi controllare i dettagli rapidi e la documentazione completa sullo stack (Hotwire).

Un grafico simile a un istogramma che mostra le prestazioni di calcolo dei telefoni più venduti
Prestazioni di elaborazione e CPU dei telefoni più venduti (Credito immagine: Addy Osmani) (Anteprima ampia)
  1. Rendering lato client o rendering lato server? Tutti e due!
    È una conversazione piuttosto accesa da avere. L'approccio finale sarebbe quello di impostare una sorta di avvio progressivo: utilizzare il rendering lato server per ottenere un rapido First Contentful Paint, ma includere anche alcuni JavaScript necessari minimi per mantenere il tempo di interazione vicino al First Contentful Paint. Se JavaScript arriva troppo tardi dopo l'FCP, il browser bloccherà il thread principale durante l'analisi, la compilazione e l'esecuzione di JavaScript scoperto in ritardo, limitando così l'interattività del sito o dell'applicazione.

    Per evitarlo, suddividi sempre l'esecuzione delle funzioni in attività asincrone separate e, ove possibile, usa requestIdleCallback . Prendi in considerazione il caricamento lento di parti dell'interfaccia utente utilizzando il supporto dinamico import() di WebPack, evitando il costo di caricamento, analisi e compilazione fino a quando gli utenti non ne hanno davvero bisogno ( grazie Addy! ).

    Come accennato in precedenza, Time to Interactive (TTI) ci dice il tempo che intercorre tra la navigazione e l'interattività. In dettaglio, la metrica viene definita osservando la prima finestra di cinque secondi dopo il rendering del contenuto iniziale, in cui nessuna attività JavaScript richiede più di 50 ms ( Attività lunghe ). Se si verifica un'attività superiore a 50 ms, la ricerca di una finestra di cinque secondi ricomincia. Di conseguenza, il browser presumerà prima di tutto di aver raggiunto Interactive , solo per passare a Frozen , solo per tornare eventualmente a Interactive .

    Una volta raggiunto Interactive , possiamo quindi, su richiesta o quando il tempo lo consente, avviare parti non essenziali dell'app. Sfortunatamente, come ha notato Paul Lewis, i framework in genere non hanno un semplice concetto di priorità che può essere mostrato agli sviluppatori, e quindi l'avvio progressivo non è facile da implementare con la maggior parte delle librerie e dei framework.

    Comunque ci stiamo arrivando. In questi giorni ci sono un paio di scelte che possiamo esplorare, e Houssein Djirdeh e Jason Miller forniscono un'eccellente panoramica di queste opzioni nel loro discorso sul Rendering sul Web e nel commento di Jason e Addy sulle moderne architetture front-end. La panoramica di seguito si basa sul loro lavoro stellare.

    • Rendering completo lato server (SSR)
      Nell'SSR classico, come WordPress, tutte le richieste vengono gestite interamente sul server. Il contenuto richiesto viene restituito come pagina HTML finita e i browser possono visualizzarlo immediatamente. Pertanto, le app SSR non possono davvero utilizzare le API DOM, ad esempio. Il divario tra First Contentful Paint e Time to Interactive è generalmente piccolo e la pagina può essere visualizzata immediatamente mentre l'HTML viene trasmesso in streaming al browser.

      Ciò evita ulteriori round trip per il recupero dei dati e la creazione di modelli sul client, poiché viene gestito prima che il browser riceva una risposta. Tuttavia, ci ritroviamo con un tempo di riflessione del server più lungo e di conseguenza Time To First Byte e non utilizziamo le funzionalità reattive e ricche delle applicazioni moderne.

    • Rendering statico
      Sviluppiamo il prodotto come un'applicazione a pagina singola, ma tutte le pagine vengono prerenderizzate in HTML statico con JavaScript minimo come fase di compilazione. Ciò significa che con il rendering statico produciamo in anticipo singoli file HTML per ogni possibile URL , cosa che non molte applicazioni possono permettersi. Ma poiché l'HTML di una pagina non deve essere generato al volo, possiamo ottenere un Time To First Byte costantemente veloce. Pertanto, possiamo visualizzare rapidamente una pagina di destinazione e quindi precaricare un framework SPA per le pagine successive. Netflix ha adottato questo approccio diminuendo il caricamento e il Time-to-Interactive del 50%.

    • Rendering lato server con (ri)idratazione (rendering universale, SSR + CSR)
      Possiamo provare a usare il meglio di entrambi i mondi: gli approcci SSR e CSR. Con l'idratazione nel mix, la pagina HTML restituita dal server contiene anche uno script che carica un'applicazione lato client completa. Idealmente, ciò ottenga un rapido First Contentful Paint (come SSR) e quindi continui il rendering con la (ri)idratazione. Sfortunatamente, questo è raramente il caso. Più spesso, la pagina sembra pronta ma non può rispondere all'input dell'utente, producendo clic di rabbia e abbandoni.

      Con React, possiamo utilizzare il modulo ReactDOMServer su un server Node come Express, quindi chiamare il metodo renderToString per eseguire il rendering dei componenti di livello superiore come una stringa HTML statica.

      Con Vue.js, possiamo utilizzare vue-server-renderer per eseguire il rendering di un'istanza Vue in HTML utilizzando renderToString . In Angular, possiamo usare @nguniversal per trasformare le richieste dei client in pagine HTML completamente visualizzate dal server. È anche possibile ottenere immediatamente un'esperienza di rendering completamente server con Next.js (React) o Nuxt.js (Vue).

      L'approccio ha i suoi lati negativi. Di conseguenza, otteniamo la piena flessibilità delle app lato client fornendo al contempo un rendering lato server più veloce, ma finiamo anche con un divario più lungo tra First Contentful Paint e Time To Interactive e un aumento del First Input Delay. La reidratazione è molto costosa e di solito questa strategia da sola non sarà abbastanza buona poiché ritarda pesantemente Time To Interactive.

    • Rendering in streaming lato server con idratazione progressiva (SSR + CSR)
      Per ridurre al minimo il divario tra Time To Interactive e First Contentful Paint, eseguiamo il rendering di più richieste contemporaneamente e inviamo il contenuto in blocchi man mano che vengono generati. Quindi non dobbiamo aspettare l'intera stringa di HTML prima di inviare contenuto al browser e quindi migliorare Time To First Byte.

      In React, invece di renderToString() , possiamo usare renderToNodeStream() per reindirizzare la risposta e inviare l'HTML in blocchi. In Vue, possiamo usare renderToStream() che può essere inviato in pipe e trasmesso in streaming. Con React Suspense, potremmo usare il rendering asincrono anche per questo scopo.

      Sul lato client, invece di avviare l'intera applicazione in una volta, avviamo i componenti progressivamente . Le sezioni delle applicazioni vengono prima suddivise in script standalone con suddivisione del codice e quindi idratate gradualmente (in base alle nostre priorità). In effetti, possiamo idratare prima i componenti critici, mentre il resto potrebbe essere idratato in seguito. Il ruolo del rendering lato client e lato server può quindi essere definito in modo diverso per componente. Possiamo quindi anche posticipare l'idratazione di alcuni componenti fino a quando non vengono visualizzati, o sono necessari per l'interazione dell'utente, o quando il browser è inattivo.

      Per Vue, Markus Oberlehner ha pubblicato una guida sulla riduzione del Time To Interactive delle app SSR utilizzando l'idratazione sull'interazione dell'utente e vue-lazy-hydration, un plug-in in fase iniziale che consente l'idratazione dei componenti sulla visibilità o sull'interazione specifica dell'utente. Il team Angular lavora sull'idratazione progressiva con Ivy Universal. Puoi implementare l'idratazione parziale anche con Preact e Next.js.

    • Rendering trisomorfo
      Con i service worker attivi, possiamo utilizzare il rendering del server di streaming per le navigazioni iniziali/non JS e quindi fare in modo che il service worker esegua il rendering di HTML per le navigazioni dopo che è stato installato. In tal caso, l'operatore del servizio esegue il prerendering del contenuto e abilita le esplorazioni in stile SPA per il rendering di nuove viste nella stessa sessione. Funziona bene quando puoi condividere lo stesso modello e codice di routing tra il server, la pagina del client e l'operatore del servizio.

    Un'illustrazione che mostra come funziona il rendering trisomorfo in 3 posizioni come il rendering DOM, il prerendering degli operatori di servizio e il rendering lato server
    Rendering trisomorfo, con lo stesso rendering del codice in 3 posizioni qualsiasi: sul server, nel DOM o in un service worker. (Fonte immagine: Google Developers) (Anteprima grande)
    • CSR con prerendering
      Il prerendering è simile al rendering lato server, ma anziché eseguire il rendering dinamico delle pagine sul server, eseguiamo il rendering dell'applicazione in HTML statico in fase di compilazione. Sebbene le pagine statiche siano completamente interattive senza molto JavaScript lato client, il prerendering funziona in modo diverso . Fondamentalmente acquisisce lo stato iniziale di un'applicazione lato client come HTML statico in fase di compilazione, mentre con il prerendering l'applicazione deve essere avviata sul client affinché le pagine siano interattive.

      Con Next.js, possiamo utilizzare l'esportazione HTML statico eseguendo il prerendering di un'app in HTML statico. In Gatsby, un generatore di siti statici open source che utilizza React, utilizza il metodo renderToStaticMarkup invece del metodo renderToString durante le build, con il blocco JS principale precaricato e le route future vengono precaricate, senza attributi DOM che non sono necessari per semplici pagine statiche.

      Per Vue, possiamo usare Vuepress per raggiungere lo stesso obiettivo. Puoi anche usare il prerender-loader con Webpack. Navi fornisce anche il rendering statico.

      Il risultato è Time To First Byte e First Contentful Paint migliori e riduciamo il divario tra Time To Interactive e First Contentful Paint. Non possiamo usare l'approccio se ci si aspetta che il contenuto cambi molto. Inoltre, tutti gli URL devono essere conosciuti in anticipo per generare tutte le pagine. Quindi alcuni componenti potrebbero essere renderizzati usando il prerendering, ma se abbiamo bisogno di qualcosa di dinamico, dobbiamo fare affidamento sull'app per recuperare il contenuto.

    • Rendering completo lato client (CSR)
      Tutta la logica, il rendering e l'avvio vengono eseguiti sul client. Il risultato è solitamente un enorme divario tra Time To Interactive e First Contentful Paint. Di conseguenza, le applicazioni spesso sembrano lente poiché l'intera app deve essere avviata sul client per eseguire il rendering di qualsiasi cosa.

      Poiché JavaScript ha un costo in termini di prestazioni, poiché la quantità di JavaScript cresce con un'applicazione, la suddivisione del codice aggressiva e il rinvio di JavaScript saranno assolutamente necessari per domare l'impatto di JavaScript. In questi casi, un rendering lato server sarà solitamente un approccio migliore nel caso in cui non sia richiesta molta interattività. Se non è un'opzione, prendi in considerazione l'utilizzo di The App Shell Model.

      In generale, la SSR è più veloce della CSR. Tuttavia, è un'implementazione abbastanza frequente per molte app là fuori.

    Quindi, lato client o lato server? In generale, è una buona idea limitare l'uso di framework completamente lato client alle pagine che li richiedono assolutamente. Per le applicazioni avanzate, non è nemmeno una buona idea affidarsi al solo rendering lato server. Sia il rendering del server che il rendering del client sono un disastro se eseguiti male.

    Sia che tu stia propendo per CSR o SSR, assicurati di eseguire il rendering di pixel importanti il ​​prima possibile e di ridurre al minimo il divario tra quel rendering e Time To Interactive. Prendi in considerazione il prerendering se le tue pagine non cambiano molto e rimanda l'avvio dei framework se puoi. Trasmetti in streaming l'HTML in blocchi con il rendering lato server e implementa l'idratazione progressiva per il rendering lato client e idrata la visibilità, l'interazione o durante i tempi di inattività per ottenere il meglio da entrambi i mondi.

Una tabella che confronta le opzioni per il rendering lato client e lato server
La gamma di opzioni per il rendering lato client e lato server. Inoltre, controlla il discorso di Jason e Houssein a Google I/O sulle implicazioni delle prestazioni dell'architettura dell'applicazione. (Fonte immagine: Jason Miller) (Anteprima grande)
Un esempio del sito Web di AirBnB che mostra senza idratazione progressiva a sinistra e con idratazione progressiva a destra
AirBnB ha sperimentato l'idratazione progressiva; rinviano i componenti non necessari, caricano sull'interazione dell'utente (scorrimento) o durante i tempi di inattività e i test dimostrano che può migliorare il TTI. (Grande anteprima)
  1. Quanto possiamo servire staticamente?
    Che tu stia lavorando su una grande applicazione o su un piccolo sito, vale la pena considerare quale contenuto potrebbe essere servito staticamente da una CDN (ad esempio JAM Stack), piuttosto che essere generato dinamicamente al volo. Anche se disponi di migliaia di prodotti e centinaia di filtri con numerose opzioni di personalizzazione, potresti comunque voler pubblicare le tue pagine di destinazione critiche in modo statico e separare queste pagine dal framework di tua scelta.

    Ci sono molti generatori di siti statici e le pagine che generano sono spesso molto veloci. Più contenuti possiamo pre-costruire in anticipo invece di generare visualizzazioni di pagina su un server o un client al momento della richiesta, migliori saranno le prestazioni che otterremo.

    In Creazione di siti Web statici parzialmente idratati e progressivamente migliorati, Markus Oberlehner mostra come creare siti Web con un generatore di siti statici e una SPA, ottenendo al contempo un miglioramento progressivo e una dimensione minima del bundle JavaScript. Markus usa Eleventy e Preact come suoi strumenti e mostra come impostare gli strumenti, aggiungere idratazione parziale, idratazione pigra, file di immissione del cliente, configurare Babel per Preact e raggruppare Preact con Rollup, dall'inizio alla fine.

    Con JAMStack utilizzato in questi giorni su siti di grandi dimensioni, è apparsa una nuova considerazione sulle prestazioni: il tempo di build . In effetti, creare anche migliaia di pagine con ogni nuova distribuzione può richiedere minuti, quindi è promettente vedere build incrementali in Gatsby che migliorano i tempi di creazione di 60 volte , con un'integrazione in soluzioni CMS popolari come WordPress, Contentful, Drupal, Netlify CMS e altri.

    Un diagramma di flusso che mostra l'Utente 1 in alto a sinistra e l'Utente 2 in basso a sinistra che mostra il processo di rigenerazione incrementale dello stato
    Rigenerazione statica incrementale con Next.js. (Credito immagine: Prisma.io) (Anteprima grande)

    Inoltre, Next.js ha annunciato la generazione statica anticipata e incrementale, che ci consente di aggiungere nuove pagine statiche in fase di esecuzione e aggiornare le pagine esistenti dopo che sono state già create, ridisegnandole in background all'arrivo del traffico .

    Hai bisogno di un approccio ancora più leggero? Nel suo intervento su Eleventy, Alpine e Tailwind: verso un Jamstack leggero, Nicola Goutay spiega le differenze tra CSR, SSR e tutto il resto e mostra come utilizzare un approccio più leggero, insieme a un repository GitHub che mostra l'approccio in pratica.

  2. Prendi in considerazione l'utilizzo del modello PRPL e dell'architettura della shell dell'app.
    Framework diversi avranno effetti diversi sulle prestazioni e richiederanno diverse strategie di ottimizzazione, quindi è necessario comprendere chiaramente tutti i dadi e i bulloni del framework su cui farete affidamento. Quando si crea un'app Web, esaminare il modello PRPL e l'architettura della shell dell'applicazione. L'idea è abbastanza semplice: spingere il codice minimo necessario per diventare interattivo per il rendering rapido del percorso iniziale, quindi utilizzare Service Worker per memorizzare nella cache e pre-memorizzare le risorse e quindi caricare i percorsi lazy necessari, in modo asincrono.
Modello PRPL nell'architettura della shell dell'applicazione
PRPL è l'acronimo di Pushing critical resource, Rendering del percorso iniziale, Pre-caching dei percorsi rimanenti e Lazy-loading dei percorsi rimanenti su richiesta.
Architettura della shell dell'applicazione
Una shell dell'applicazione è il minimo HTML, CSS e JavaScript che alimenta un'interfaccia utente.
  1. Hai ottimizzato le prestazioni delle tue API?
    Le API sono canali di comunicazione per un'applicazione per esporre i dati ad applicazioni interne e di terze parti tramite endpoint . Quando si progetta e si costruisce un'API, è necessario un protocollo ragionevole per consentire la comunicazione tra il server e le richieste di terze parti. Il Representational State Transfer ( REST ) ​​è una scelta logica ben consolidata: definisce un insieme di vincoli che gli sviluppatori seguono per rendere i contenuti accessibili in modo performante, affidabile e scalabile. I servizi Web conformi ai vincoli REST sono chiamati servizi Web RESTful .

    Come con le buone vecchie richieste HTTP, quando i dati vengono recuperati da un'API, qualsiasi ritardo nella risposta del server si propagherà all'utente finale, ritardando quindi il rendering . Quando una risorsa vuole recuperare alcuni dati da un'API, dovrà richiedere i dati dall'endpoint corrispondente. Un componente che esegue il rendering dei dati da diverse risorse, ad esempio un articolo con commenti e foto dell'autore in ogni commento, potrebbe richiedere diversi viaggi di andata e ritorno sul server per recuperare tutti i dati prima che possano essere visualizzati. Inoltre, la quantità di dati restituita tramite REST è spesso superiore a quella necessaria per eseguire il rendering di quel componente.

    Se molte risorse richiedono dati da un'API, l'API potrebbe diventare un collo di bottiglia delle prestazioni. GraphQL fornisce una soluzione efficiente a questi problemi. Di per sé, GraphQL è un linguaggio di query per la tua API e un runtime lato server per l'esecuzione di query utilizzando un sistema di tipi che definisci per i tuoi dati. A differenza di REST, GraphQL può recuperare tutti i dati in un'unica richiesta e la risposta sarà esattamente quella richiesta, senza sovra o sotto -prelievo dei dati come accade in genere con REST.

    Inoltre, poiché GraphQL utilizza lo schema (metadati che raccontano come sono strutturati i dati), può già organizzare i dati nella struttura preferita, quindi, ad esempio, con GraphQL, potremmo rimuovere il codice JavaScript utilizzato per gestire la gestione dello stato, producendo un codice dell'applicazione più pulito che viene eseguito più velocemente sul client.

    Se vuoi iniziare con GraphQL o riscontrare problemi di prestazioni, questi articoli potrebbero essere molto utili:

    • Un primer GraphQL: perché abbiamo bisogno di un nuovo tipo di API di Eric Baer,
    • A GraphQL Primer: The Evolution Of API Design di Eric Baer,
    • Progettazione di un server GraphQL per prestazioni ottimali di Leonardo Losoviz,
    • Le prestazioni di GraphQL spiegate da Wojciech Trocki.
Due esempi di interfacce mobili per i messaggi durante l'utilizzo di Redux/REST (a sinistra) e Apollo/GraphQL (a destra)
Una differenza tra REST e GraphQL, illustrata tramite una conversazione tra Redux + REST a sinistra, un Apollo + GraphQL a destra. (Fonte immagine: Hacker Noon) (Anteprima grande)
  1. Utilizzerai AMP o Instant Articles?
    A seconda delle priorità e della strategia della tua organizzazione, potresti prendere in considerazione l'utilizzo di AMP di Google o di Articoli istantanei di Facebook o Apple News di Apple. Puoi ottenere buone prestazioni senza di loro, ma AMP fornisce un solido framework di prestazioni con una rete di distribuzione di contenuti (CDN) gratuita , mentre gli articoli istantanei aumenteranno la tua visibilità e le tue prestazioni su Facebook.

    Il vantaggio apparentemente ovvio di queste tecnologie per gli utenti sono le prestazioni garantite , quindi a volte potrebbero persino preferire AMP-/Apple News/Instant Pages-link rispetto a pagine "normali" e potenzialmente gonfie. Per i siti Web ricchi di contenuti che hanno a che fare con molti contenuti di terze parti, queste opzioni potrebbero potenzialmente aiutare ad accelerare notevolmente i tempi di rendering.

    A meno che non lo facciano. Secondo Tim Kadlec, ad esempio, "i documenti AMP tendono ad essere più veloci delle loro controparti, ma non significano necessariamente che una pagina sia performante. AMP non è ciò che fa la differenza maggiore dal punto di vista delle prestazioni".

    Un vantaggio per il proprietario del sito web è evidente: la rilevabilità di questi formati sulle rispettive piattaforme e una maggiore visibilità nei motori di ricerca.

    Beh, almeno è così che era una volta. Poiché AMP non è più un requisito per le Top Stories , gli editori potrebbero invece passare da AMP a uno stack tradizionale ( grazie, Barry! ).

    Tuttavia, puoi anche creare AMP Web progressivi riutilizzando gli AMP come origine dati per la tua PWA. Svantaggio? Ovviamente, una presenza in un giardino recintato mette gli sviluppatori nella posizione di produrre e mantenere una versione separata dei loro contenuti, e in caso di articoli istantanei e notizie di Apple senza URL reali (grazie Addy, Jeremy!) .

  2. Scegli saggiamente la tua CDN.
    Come accennato in precedenza, a seconda della quantità di dati dinamici di cui disponi, potresti essere in grado di "esternalizzare" parte del contenuto a un generatore di siti statici, spingendolo su una CDN e servendo da esso una versione statica, evitando così richieste al server. In effetti, alcuni di questi generatori sono in realtà compilatori di siti Web con molte ottimizzazioni automatiche fornite immediatamente. Man mano che i compilatori aggiungono ottimizzazioni nel tempo, l'output compilato diventa più piccolo e più veloce nel tempo.

    Si noti che le CDN possono anche servire (e scaricare) contenuto dinamico. Quindi, non è necessario limitare la tua CDN alle risorse statiche. Verifica se la tua CDN esegue compressione e conversione (ad es. ottimizzazione e ridimensionamento dell'immagine ai margini), se forniscono supporto per i server worker, test A/B e include edge-side, che assemblano parti statiche e dinamiche delle pagine a bordo della CDN (ovvero il server più vicino all'utente) e altre attività. Inoltre, controlla se la tua CDN supporta HTTP su QUIC (HTTP/3).

    Katie Hempenius ha scritto una fantastica guida ai CDN che fornisce spunti su come scegliere un buon CDN , come perfezionarlo e tutte le piccole cose da tenere a mente quando ne valuta uno. In generale, è una buona idea memorizzare nella cache il contenuto nel modo più aggressivo possibile e abilitare le funzionalità delle prestazioni CDN come Brotli, TLS 1.3, HTTP/2 e HTTP/3.

    Nota : in base alla ricerca di Patrick Meenan e Andy Davies, la definizione delle priorità HTTP/2 è effettivamente interrotta su molte CDN, quindi fai attenzione quando scegli una CDN. Patrick ha maggiori dettagli nel suo intervento sulla priorità HTTP/2 ( grazie, Barry! ).

    Anteprima CDNPerf dei nomi CDN e della velocità della query in ms
    CDNPerf misura la velocità delle query per le CDN raccogliendo e analizzando 300 milioni di test ogni giorno. (Grande anteprima)

    Quando scegli una CDN, puoi utilizzare questi siti di confronto con una panoramica dettagliata delle loro caratteristiche:

    • Confronto CDN, una matrice di confronto CDN per Cloudfront, Aazure, KeyCDN, Fastly, Verizon, Stackpach, Akamai e molti altri.
    • CDN Perf misura la velocità delle query per le CDN raccogliendo e analizzando 300 milioni di test ogni giorno, con tutti i risultati basati sui dati RUM di utenti di tutto il mondo. Controlla anche il confronto delle prestazioni DNS e il confronto delle prestazioni del cloud.
    • CDN Planet Guides fornisce una panoramica delle CDN per argomenti specifici, come Serve Stale, Purge, Origin Shield, Prefetch e Compression.
    • Web Almanac: CDN Adoption and Usage fornisce informazioni dettagliate sui principali provider CDN, sulla loro gestione RTT e TLS, sui tempi di negoziazione TLS, sull'adozione di HTTP/2 e altro. (Purtroppo i dati sono solo del 2019).

Ottimizzazioni degli asset

  1. Usa Brotli per la compressione del testo normale.
    Nel 2015, Google ha introdotto Brotli, un nuovo formato di dati senza perdita di dati open source, che ora è supportato in tutti i browser moderni. La libreria Brotli open source, che implementa un codificatore e un decoder per Brotli, ha 11 livelli di qualità predefiniti per l'encoder, con un livello di qualità superiore che richiede più CPU in cambio di un migliore rapporto di compressione. Una compressione più lenta alla fine porterà a tassi di compressione più elevati, tuttavia Brotli si decomprime rapidamente. Vale la pena notare però che Brotli con il livello di compressione 4 è più piccolo e si comprime più velocemente di Gzip.

    In pratica, Brotli sembra essere molto più efficace di Gzip. Le opinioni e le esperienze differiscono, ma se il tuo sito è già ottimizzato con Gzip, potresti aspettarti miglioramenti almeno a una cifra e nella migliore delle ipotesi miglioramenti a due cifre nella riduzione delle dimensioni e nei tempi FCP. Puoi anche stimare i risparmi di compressione Brotli per il tuo sito.

    I browser accetteranno Brotli solo se l'utente sta visitando un sito Web tramite HTTPS. Brotli è ampiamente supportato e molti CDN lo supportano (Akamai, Netlify Edge, AWS, KeyCDN, Fastly (attualmente solo come pass-through), Cloudflare, CDN77) e puoi abilitare Brotli anche su CDN che non lo supportano ancora (con un addetto ai servizi).

    Il problema è che, poiché la compressione di tutte le risorse con Brotli a un livello di compressione elevato è costosa, molti provider di hosting non possono utilizzarlo su vasta scala solo a causa dell'enorme sovraccarico di costi che produce. Infatti, al più alto livello di compressione, Brotli è così lento che qualsiasi potenziale aumento delle dimensioni del file potrebbe essere annullato dal tempo impiegato dal server per iniziare a inviare la risposta mentre attende di comprimere dinamicamente l'asset. (Ma se hai tempo durante il tempo di costruzione con la compressione statica, ovviamente, sono preferibili impostazioni di compressione più elevate.)

    Un confronto mostrato come un grafico dei baffi che mostra vari metodi di compressione in tre diversi tempi di back-end: minimo, medio e 90° percentile
    Confronto dei tempi di back-end di vari metodi di compressione. Non sorprende che Brotli sia più lento di gzip (per ora). (Grande anteprima)

    Questo potrebbe cambiare però. Il formato di file Brotli include un dizionario statico integrato e, oltre a contenere varie stringhe in più lingue, supporta anche l'opzione di applicare più trasformazioni a quelle parole, aumentandone la versatilità. Nella sua ricerca, Felix Hanau ha scoperto un modo per migliorare la compressione ai livelli da 5 a 9 utilizzando "un sottoinsieme del dizionario più specializzato rispetto a quello predefinito" e basandosi sull'intestazione Content-Type per dire al compressore se deve utilizzare un dizionario per HTML, JavaScript o CSS. Il risultato è stato un "impatto trascurabile sulle prestazioni (dall'1% al 3% in più di CPU rispetto al 12% normalmente) durante la compressione di contenuti Web a livelli di compressione elevati, utilizzando un approccio di utilizzo limitato del dizionario".

    Un grafico a barre che mostra il guadagno di compressione utilizzando i dizionari ridotti Brotli al livello 5
    Con l'approccio del dizionario migliorato, possiamo comprimere le risorse più velocemente a livelli di compressione più elevati, il tutto utilizzando solo dall'1% al 3% in più di CPU. Normalmente, il livello di compressione 6 su 5 aumenterebbe l'utilizzo della CPU fino al 12%. (Grande anteprima)

    Inoltre, con la ricerca di Elena Kirilenko, possiamo ottenere una ricompressione Brotli rapida ed efficiente utilizzando precedenti artefatti di compressione. Secondo Elena, "una volta che abbiamo una risorsa compressa tramite Brotli, e stiamo cercando di comprimere il contenuto dinamico al volo, in cui il contenuto assomiglia a quello a nostra disposizione in anticipo, possiamo ottenere miglioramenti significativi nei tempi di compressione. "

    Quante volte è il caso? Ad esempio con la consegna di sottoinsiemi di bundle JavaScript (ad esempio quando parti del codice sono già memorizzate nella cache del client o con bundle dinamici che servono con WebBundles). Oppure con HTML dinamico basato su modelli noti in anticipo o caratteri WOFF2 con sottoinsiemi dinamici . Secondo Elena, possiamo ottenere un miglioramento del 5,3% sulla compressione e del 39% sulla velocità di compressione rimuovendo il 10% del contenuto e tassi di compressione migliori del 3,2% e una compressione più veloce del 26% rimuovendo il 50% del contenuto.

    La compressione Brotli sta migliorando, quindi se riesci a bypassare il costo della compressione dinamica delle risorse statiche, ne vale sicuramente la pena. Inutile dire che Brotli può essere utilizzato per qualsiasi payload in testo normale: HTML, CSS, SVG, JavaScript, JSON e così via.

    Nota : all'inizio del 2021, circa il 60% delle risposte HTTP viene fornito senza compressione basata su testo, con il 30,82% di compressione con Gzip e il 9,1% di compressione con Brotli (sia su dispositivi mobili che desktop). Ad esempio, il 23,4% delle pagine Angular non viene compresso (tramite gzip o Brotli). Tuttavia, spesso attivare la compressione è una delle vittorie più facili per migliorare le prestazioni con un semplice tocco di un interruttore.

    La strategia? Precomprime le risorse statiche con Brotli+Gzip al livello più alto e comprimi l'HTML (dinamico) al volo con Brotli al livello 4–6. Assicurati che il server gestisca correttamente la negoziazione dei contenuti per Brotli o Gzip.

Un grafico a barre che mostra gli algoritmi di compressione per le richieste HTTP secondo il report Web Almanax 2020
Delle risorse servite compresse nel 2020, il 22,59% è compresso con Brotli. Circa il 77,39% è compresso con gzip. (Fonte immagine: Web Almanac: Compression) (Anteprima grande)
  1. Utilizziamo il caricamento adattivo dei media e i suggerimenti dei client?
    Proviene dalla terra delle vecchie notizie, ma è sempre un buon promemoria per utilizzare immagini reattive con srcset , sizes e l'elemento <picture> . Soprattutto per i siti con un elevato ingombro multimediale, possiamo fare un ulteriore passo avanti con il caricamento adattivo dei media (in questo esempio React + Next.js), offrendo un'esperienza leggera a reti lente e dispositivi con memoria insufficiente e un'esperienza completa su reti veloci e -dispositivi di memoria. Nel contesto di React, possiamo ottenerlo con suggerimenti client sul server e hook adattivi di reazione sul client.

    Il futuro delle immagini reattive potrebbe cambiare radicalmente con l'adozione più ampia dei suggerimenti dei clienti. I suggerimenti del client sono campi di intestazione della richiesta HTTP, ad esempio DPR , Viewport-Width , Width , Save-Data , Accept (per specificare le preferenze del formato immagine) e altri. Dovrebbero informare il server sulle specifiche del browser, dello schermo, della connessione dell'utente, ecc.

    Di conseguenza, il server può decidere come riempire il layout con immagini di dimensioni adeguate e servire solo queste immagini nei formati desiderati. Con i suggerimenti per il client, spostiamo la selezione delle risorse dal markup HTML e nella negoziazione richiesta-risposta tra il client e il server.

    Un'illustrazione che mostra come è possibile utilizzare il servizio multimediale adattivo inviando risoluzioni diverse agli utenti a seconda della capacità della rete
    Servizi multimediali adattivi in ​​uso. Inviamo un segnaposto con testo agli utenti offline, un'immagine a bassa risoluzione agli utenti 2G, un'immagine ad alta risoluzione agli utenti 3G e un video HD agli utenti 4G. Tramite il caricamento rapido di pagine Web su un feature phone da $ 20. (Grande anteprima)

    Come Ilya Grigorik ha notato tempo fa, i suggerimenti dei clienti completano il quadro: non sono un'alternativa alle immagini reattive. "L'elemento <picture> fornisce il necessario controllo della direzione artistica nel markup HTML. I suggerimenti del client forniscono annotazioni sulle richieste di immagini risultanti che consentono l'automazione della selezione delle risorse. Service Worker fornisce funzionalità complete di gestione delle richieste e delle risposte sul client".

    Un addetto al servizio potrebbe, ad esempio, aggiungere nuovi valori di intestazione dei suggerimenti client alla richiesta, riscrivere l'URL e indirizzare la richiesta di immagine a una CDN, adattare la risposta in base alla connettività e alle preferenze dell'utente, ecc. Vale non solo per le risorse immagine, ma praticamente anche per tutte le altre richieste.

    Per i client che supportano i suggerimenti client, è possibile misurare un risparmio del 42% di byte sulle immagini e oltre 1 MB di byte in meno per il 70° percentile. Su Smashing Magazine, potremmo anche misurare un miglioramento del 19-32%. I suggerimenti per i client sono supportati nei browser basati su Chromium, ma sono ancora presi in considerazione in Firefox.

    Tuttavia, se fornisci sia il normale markup delle immagini reattive che il tag <meta> per i suggerimenti client, un browser di supporto valuterà il markup delle immagini reattive e richiederà l'origine dell'immagine appropriata utilizzando le intestazioni HTTP dei suggerimenti client.

  2. Usiamo immagini reattive per le immagini di sfondo?
    Dovremmo sicuramente! Con image-set , ora supportato in Safari 14 e nella maggior parte dei browser moderni ad eccezione di Firefox, possiamo offrire anche immagini di sfondo reattive:

    background-image: url("fallback.jpg"); background-image: image-set( "photo-small.jpg" 1x, "photo-large.jpg" 2x, "photo-print.jpg" 600dpi);

    Fondamentalmente possiamo servire in modo condizionale immagini di sfondo a bassa risoluzione con un descrittore 1x e immagini ad alta risoluzione con descrittore 2x e persino un'immagine di qualità di stampa con descrittore 600dpi . Attenzione però: i browser non forniscono alcuna informazione speciale sulle immagini di sfondo alla tecnologia assistiva, quindi idealmente queste foto sarebbero solo decorazioni.

  3. Usiamo WebP?
    La compressione delle immagini è spesso considerata una rapida vittoria, ma nella pratica è ancora fortemente sottoutilizzata. Ovviamente le immagini non bloccano il rendering, ma contribuiscono pesantemente a scarsi punteggi LCP e molto spesso sono semplicemente troppo pesanti e troppo grandi per il dispositivo su cui vengono consumate.

    Quindi, come minimo, potremmo esplorare utilizzando il formato WebP per le nostre immagini. In effetti, la saga di WebP si è avvicinata alla fine lo scorso anno con Apple che ha aggiunto il supporto per WebP in Safari 14. Quindi, dopo molti anni di discussioni e dibattiti, ad oggi WebP è supportato in tutti i browser moderni. Quindi possiamo fornire immagini WebP con l'elemento <picture> e un fallback JPEG se necessario (vedi snippet di codice di Andreas Bovens) o utilizzando la negoziazione del contenuto (usando le intestazioni Accept ).

    Tuttavia, WebP non è privo di svantaggi . Sebbene le dimensioni dei file di immagine WebP siano confrontate con gli equivalenti Guetzli e Zopfli, il formato non supporta il rendering progressivo come JPEG, motivo per cui gli utenti potrebbero vedere l'immagine finita più velocemente con un buon vecchio JPEG anche se le immagini WebP potrebbero diventare più veloci attraverso la rete. Con JPEG, possiamo offrire un'esperienza utente "decente" con la metà o addirittura un quarto dei dati e caricare il resto in un secondo momento, piuttosto che avere un'immagine semivuota come nel caso di WebP.

    La tua decisione dipenderà da cosa cerchi: con WebP ridurrai il carico utile e con JPEG migliorerai le prestazioni percepite. Puoi saperne di più su WebP in WebP Rewind talk di Pascal Massimino di Google.

    Per la conversione in WebP, puoi utilizzare WebP Converter, cwebp o libwebp. Anche Ire Aderinokun ha un tutorial molto dettagliato sulla conversione delle immagini in WebP, così come Josh Comeau nel suo pezzo sull'adozione dei moderni formati di immagine.

    Una diapositiva utilizzata per il discorso di Pascal Massimino intitolato Immagine pronta: webp rewind
    Un approfondito talk su WebP: WebP Rewind di Pascal Massimino. (Grande anteprima)

    Sketch supporta nativamente WebP e le immagini WebP possono essere esportate da Photoshop utilizzando un plug-in WebP per Photoshop. Ma sono disponibili anche altre opzioni.

    Se stai utilizzando WordPress o Joomla, ci sono estensioni per aiutarti a implementare facilmente il supporto per WebP, come Optimus e Cache Enabler per WordPress e l'estensione supportata da Joomla (tramite Cody Arsenault). Puoi anche astrarre l'elemento <picture> con React, componenti in stile o gatsby-image.

    Ah - spina spudorata! — Jeremy Wagner ha persino pubblicato un libro Smashing su WebP che potresti voler controllare se sei interessato a tutto ciò che riguarda WebP.

  4. Usiamo AVIF?
    Potresti aver sentito la grande novità: l'AVIF è atterrato. È un nuovo formato immagine derivato dai fotogrammi chiave del video AV1. È un formato aperto e privo di royalty che supporta compressione, animazione, canale alfa con perdita e può gestire linee nitide e colori solidi (che era un problema con JPEG), fornendo risultati migliori in entrambi.

    Infatti, rispetto a WebP e JPEG, AVIF ha prestazioni significativamente migliori , producendo risparmi sulla dimensione media del file fino al 50% con la stessa ((dis)somiglianza DSSIM tra due o più immagini utilizzando un algoritmo che si avvicina alla visione umana). In effetti, nel suo post approfondito sull'ottimizzazione del caricamento delle immagini, Malte Ubl osserva che AVIF "supera costantemente JPEG in modo molto significativo. Questo è diverso da WebP che non produce sempre immagini più piccole di JPEG e potrebbe effettivamente essere un net- perdita per mancanza di supporto per il caricamento progressivo."

    Un frammento di codice che mostra AVIF come miglioramento progressivo
    Possiamo utilizzare AVIF come miglioramento progressivo, fornendo WebP o JPEG o PNG a browser meno recenti. (Grande anteprima). Vedere la visualizzazione del testo normale di seguito.

    Ironia della sorte, AVIF può funzionare anche meglio dei grandi SVG, anche se ovviamente non dovrebbe essere visto come un sostituto degli SVG. È anche uno dei primi formati di immagine a supportare il supporto del colore HDR; offrendo maggiore luminosità, profondità di bit di colore e gamme di colori. L'unico aspetto negativo è che attualmente AVIF non supporta la decodifica progressiva delle immagini (ancora?) e, analogamente a Brotli, una codifica ad alto tasso di compressione è attualmente piuttosto lenta, sebbene la decodifica sia veloce.

    AVIF è attualmente supportato in Chrome, Firefox e Opera e il supporto in Safari dovrebbe arrivare presto (poiché Apple è un membro del gruppo che ha creato AV1).

    Qual è il modo migliore per offrire immagini in questi giorni , allora? Per illustrazioni e immagini vettoriali, SVG (compresso) è senza dubbio la scelta migliore. Per le foto, utilizziamo metodi di negoziazione dei contenuti con l'elemento picture . Se l'AVIF è supportato, inviamo un'immagine AVIF; in caso contrario, torniamo prima a WebP e, se anche WebP non è supportato, passiamo a JPEG o PNG come fallback (applicando le condizioni @media se necessario):

    <picture> <source type="image/avif"> <source type="image/webp"> <img src="image.jpg" alt="Photo" width="450" height="350"> </picture>

    Francamente, è più probabile che utilizzeremo alcune condizioni all'interno dell'elemento picture :

    <picture> <source type="image/avif" /> <source type="image/webp" /> <source type="image/jpeg" /> <img src="fallback-image.jpg" alt="Photo" width="450" height="350"> </picture>
    <picture> <source type="image/avif" /> <source type="image/webp" /> <source type="image/jpeg" /> <img src="fallback-image.jpg" alt="Photo" width="450" height="350"> </picture>

    Puoi andare ancora oltre scambiando immagini animate con immagini statiche per i clienti che optano per meno movimento con prefers-reduced-motion :

    <picture> <source media="(prefers-reduced-motion: reduce)" type="image/avif"></source> <source media="(prefers-reduced-motion: reduce)" type="image/jpeg"></source> <source type="image/avif"></source> <img src="motion.jpg" alt="Animated AVIF"> </picture>
    <picture> <source media="(prefers-reduced-motion: reduce)" type="image/avif"></source> <source media="(prefers-reduced-motion: reduce)" type="image/jpeg"></source> <source type="image/avif"></source> <img src="motion.jpg" alt="Animated AVIF"> </picture>

    Nel corso dei due mesi, AVIF ha guadagnato terreno:

    • Possiamo testare i fallback WebP/AVIF nel pannello Rendering in DevTools.
    • Possiamo usare Squoosh, AVIF.io e libavif per codificare, decodificare, comprimere e convertire file AVIF.
    • Possiamo usare il componente AVIF Preact di Jake Archibald che decodifica un file AVIF in un lavoratore e visualizza il risultato su una tela,
    • Per fornire AVIF solo ai browser di supporto, possiamo utilizzare un plug-in PostCSS insieme a uno script 315B per utilizzare AVIF nelle dichiarazioni CSS.
    • Siamo in grado di fornire progressivamente nuovi formati di immagine con CSS e Cloudlare Workers per alterare dinamicamente il documento HTML restituito, deducendo le informazioni dall'intestazione di accept e quindi aggiungere le webp/avif ecc. a seconda dei casi.
    • AVIF è già disponibile in Cloudinary (con limiti di utilizzo), Cloudflare supporta AVIF in Image Resizing e puoi abilitare AVIF con intestazioni AVIF personalizzate in Netlify.
    • Quando si tratta di animazione, AVIF si comporta così come <img src=mp4> di Safari, superando GIF e WebP in generale, ma MP4 ha comunque prestazioni migliori.
    • In generale, per le animazioni, AVC1 (h264) > HVC1 > WebP > AVIF > GIF, supponendo che i browser basati su Chromium supportino sempre <img src=mp4> .
    • Puoi trovare maggiori dettagli su AVIF in AVIF per il discorso sulla codifica delle immagini di nuova generazione di Aditya Mavlankar da Netflix e nel discorso sul formato immagine AVIF di Kornel Lesinski di Cloudflare.
    • Un ottimo riferimento per tutto AVIF: il post completo di Jake Archibald su AVIF è arrivato.

    Quindi il futuro AVIF è allora ? Jon Sneyers non è d'accordo: AVIF ha prestazioni peggiori del 60% rispetto a JPEG XL, un altro formato gratuito e aperto sviluppato da Google e Cloudinary. In effetti, JPEG XL sembra funzionare molto meglio su tutta la linea. Tuttavia, JPEG XL è ancora solo nelle fasi finali della standardizzazione e non funziona ancora in nessun browser. (Da non confondere con il JPEG-XR di Microsoft proveniente dal buon vecchio Internet Explorer 9 volte).

Generatore di punti di interruzione immagine reattiva
Il generatore di punti di interruzione dell'immagine reattiva automatizza le immagini e la generazione di markup.
  1. I file JPEG/PNG/SVG sono ottimizzati correttamente?
    Quando lavori su una pagina di destinazione in cui è fondamentale che l'immagine di un eroe si carichi in modo incredibilmente veloce, assicurati che i JPEG siano progressivi e compressi con mozJPEG (che migliora il tempo di rendering iniziale manipolando i livelli di scansione) o Guetzli, l'open source di Google codificatore incentrato sulle prestazioni percettive e sull'utilizzo degli apprendimenti di Zopfli e WebP. L'unico aspetto negativo: tempi di elaborazione lenti (un minuto di CPU per megapixel).

    Per PNG possiamo usare Pingo e per SVG possiamo usare SVGO o SVGOMG. E se hai bisogno di visualizzare in anteprima e copiare o scaricare rapidamente tutte le risorse SVG da un sito Web, svg-grabber può farlo anche per te.

    Ogni singolo articolo sull'ottimizzazione delle immagini lo direbbe, ma vale sempre la pena ricordare di mantenere le risorse vettoriali pulite e compatte. Assicurati di ripulire le risorse inutilizzate, rimuovere i metadati non necessari e ridurre il numero di punti di percorso nella grafica (e quindi il codice SVG). ( Grazie, Jeremy! )

    Ci sono anche utili strumenti online disponibili però:

    • Usa Squoosh per comprimere, ridimensionare e manipolare le immagini ai livelli di compressione ottimali (lossy o lossless),
    • Usa Guetzli.it per comprimere e ottimizzare le immagini JPEG con Guetzli, che funziona bene per immagini con bordi netti e colori solidi (ma potrebbe essere un po' più lento)).
    • Utilizza Responsive Image Breakpoints Generator o un servizio come Cloudinary o Imgix per automatizzare l'ottimizzazione delle immagini. Inoltre, in molti casi, l'utilizzo srcset e sizes da solo raccoglierà vantaggi significativi.
    • Per verificare l'efficienza del tuo markup reattivo, puoi utilizzare imaging-heap, uno strumento a riga di comando che misura l'efficienza tra le dimensioni del viewport e i rapporti pixel del dispositivo.
    • Puoi aggiungere la compressione automatica delle immagini ai tuoi flussi di lavoro GitHub, in modo che nessuna immagine possa raggiungere la produzione non compressa. L'azione utilizza mozjpeg e libvips che funzionano con PNG e JPG.
    • Per ottimizzare l'archiviazione internamente, puoi utilizzare il nuovo formato Lepton di Dropbox per comprimere i file JPEG senza perdite di una media del 22%.
    • Usa BlurHash se desideri mostrare un'immagine segnaposto in anticipo. BlurHash prende un'immagine e ti dà una breve stringa (solo 20-30 caratteri!) che rappresenta il segnaposto per questa immagine. La stringa è abbastanza corta da poter essere facilmente aggiunta come campo in un oggetto JSON.
    Un confronto di un'interfaccia senza segnaposto immagine a sinistra e con segnaposto mostrati a destra
    BlurHash è una rappresentazione minuscola e compatta di un segnaposto per un'immagine. (Grande anteprima)

    A volte l'ottimizzazione delle immagini da sola non basta. Per migliorare il tempo necessario per avviare il rendering di un'immagine critica, carica in modo lazy le immagini meno importanti e rinvia gli script da caricare dopo che le immagini critiche sono già state renderizzate. Il modo più a prova di proiettile è il lazy-loading ibrido, quando utilizziamo il lazy-loading e lazyload nativi, una libreria che rileva eventuali modifiche alla visibilità attivate dall'interazione dell'utente (con IntersectionObserver che esploreremo in seguito). Inoltre:

    • Prendi in considerazione il precaricamento delle immagini critiche, in modo che un browser non le scopra troppo tardi. Per le immagini di sfondo, se vuoi essere ancora più aggressivo, puoi aggiungere l'immagine come un'immagine normale con <img src> , quindi nasconderla dallo schermo.
    • Considerare lo scambio di immagini con l'attributo Dimensioni specificando diverse dimensioni di visualizzazione dell'immagine a seconda delle query multimediali, ad esempio per manipolare le sizes per scambiare le sorgenti in un componente lente di ingrandimento.
    • Esamina le incoerenze di download delle immagini per evitare download imprevisti per le immagini in primo piano e di sfondo. Fai attenzione alle immagini che vengono caricate per impostazione predefinita, ma potrebbero non essere mai visualizzate, ad esempio nei caroselli, nelle fisarmoniche e nelle gallerie di immagini.
    • Assicurati di impostare sempre width e height sulle immagini. Fai attenzione alla proprietà aspect-ratio in CSS e all'attributo intrinsicsize che ci consentirà di impostare proporzioni e dimensioni per le immagini, in modo che il browser possa riservare uno slot di layout predefinito in anticipo per evitare salti di layout durante il caricamento della pagina.
    Uno screenshot del codice che mostra gli elementi della parte superiore del riempimento e delle proporzioni in uso in un editor
    Dovrebbe essere solo questione di settimane o mesi ora, con le proporzioni che atterrano nei browser. Già in Safari Technical Preview 118. Attualmente dietro la bandiera in Firefox e Chrome. (Grande anteprima)

    Se ti senti avventuroso, puoi tagliare e riorganizzare i flussi HTTP/2 utilizzando Edge worker, fondamentalmente un filtro in tempo reale che vive sulla CDN, per inviare immagini più velocemente attraverso la rete. I lavoratori perimetrali utilizzano flussi JavaScript che utilizzano blocchi che puoi controllare (in pratica sono JavaScript che vengono eseguiti sul bordo CDN che possono modificare le risposte di streaming), in modo da poter controllare la consegna delle immagini.

    Con un addetto ai servizi, è troppo tardi perché non puoi controllare cosa c'è sul cavo, ma funziona con i lavoratori Edge. Quindi puoi usarli sopra i JPEG statici salvati progressivamente per una particolare pagina di destinazione.

    Uno screenshot dello strumento della riga di comando dell'heap di imaging che mostra una tabella con varie dimensioni della finestra e rapporti pixel del dispositivo
    Un output di esempio di imaging-heap, uno strumento a riga di comando che misura l'efficienza tra le dimensioni del viewport e i rapporti pixel del dispositivo. (Fonte immagine) (Anteprima grande)

    Non buono abbastanza? Bene, puoi anche migliorare le prestazioni percepite per le immagini con la tecnica delle immagini di sfondo multiple. Tieni presente che giocare con il contrasto e sfocare i dettagli non necessari (o rimuovere i colori) può anche ridurre le dimensioni del file. Ah, devi ingrandire una piccola foto senza perdere in qualità? Prendi in considerazione l'utilizzo di Letsenhance.io.

    Queste ottimizzazioni finora coprono solo le basi. Addy Osmani ha pubblicato una guida molto dettagliata sull'ottimizzazione dell'immagine essenziale che approfondisce i dettagli della compressione dell'immagine e della gestione del colore. Ad esempio, potresti sfocare parti non necessarie dell'immagine (applicando loro un filtro sfocatura gaussiana) per ridurre le dimensioni del file e alla fine potresti persino iniziare a rimuovere i colori o trasformare l'immagine in bianco e nero per ridurre ulteriormente le dimensioni . Per le immagini di sfondo, anche l'esportazione di foto da Photoshop con una qualità dallo 0 al 10% può essere assolutamente accettabile.

    Su Smashing Magazine, utilizziamo il suffisso -opt per i nomi delle immagini, ad esempio brotli-compression-opt.png ; ogni volta che un'immagine contiene quel suffisso, tutti nel team sanno che l'immagine è già stata ottimizzata.

    Ah, e non utilizzare JPEG-XR sul Web: "l'elaborazione della decodifica di JPEG-XR lato software sulla CPU annulla e addirittura supera l'impatto potenzialmente positivo del risparmio di dimensioni dei byte, specialmente nel contesto delle SPA" (non da confondere con Cloudinary/JPEG XL di Google però).

Sostituzione delle GIF animate con l'elemento video con un risparmio di oltre l'80%.
Addy Osmani consiglia di sostituire le GIF animate con video in linea in loop. La differenza di dimensione del file è notevole (risparmio dell'80%). (Grande anteprima)
  1. I video sono ottimizzati correttamente?
    Finora abbiamo trattato le immagini, ma abbiamo evitato una conversazione sulle buone vecchie GIF. Nonostante il nostro amore per le GIF, è davvero il momento di abbandonarle per sempre (almeno nei nostri siti Web e app). Invece di caricare GIF animate pesanti che influiscono sia sulle prestazioni di rendering che sulla larghezza di banda, è una buona idea passare a WebP animato (con GIF come fallback) o sostituirle con video HTML5 in loop del tutto.

    A differenza delle immagini, i browser non precaricano il contenuto <video> , ma i video HTML5 tendono ad essere molto più leggeri e più piccoli delle GIF. Non è un'opzione? Bene, almeno possiamo aggiungere una compressione con perdita di dati alle GIF con Lossy GIF, gifsicle o giflossy.

    I test di Colin Bendell mostrano che i video inline all'interno dei tag img in Safari Technology Preview vengono visualizzati almeno 20 volte più velocemente e decodificano 7 volte più velocemente dell'equivalente GIF, oltre ad essere una frazione delle dimensioni del file. Tuttavia, non è supportato in altri browser.

    Nella terra delle buone notizie, i formati video sono progrediti enormemente nel corso degli anni. Per molto tempo abbiamo sperato che WebM diventasse il formato per dominarli tutti e WebP (che è fondamentalmente un'immagine fissa all'interno del contenitore video WebM) diventasse un sostituto per formati di immagine datati. In effetti, Safari ora supporta WebP, ma nonostante WebP e WebM abbiano ottenuto supporto in questi giorni, la svolta in realtà non è avvenuta.

    Tuttavia, potremmo utilizzare WebM per la maggior parte dei browser moderni disponibili:

    <!-- By Houssein Djirdeh. https://web.dev/replace-gifs-with-videos/ --> <!-- A common scenartio: MP4 with a WEBM fallback. --> <video autoplay loop muted playsinline> <source src="my-animation.webm" type="video/webm"> <source src="my-animation.mp4" type="video/mp4"> </video>

    Ma forse potremmo rivisitarlo del tutto. Nel 2018, l'Alliance of Open Media ha rilasciato un nuovo promettente formato video chiamato AV1 . AV1 ha una compressione simile al codec H.265 (l'evoluzione di H.264) ma a differenza di quest'ultimo, AV1 è gratuito. Il prezzo della licenza H.265 ha spinto i fornitori di browser ad adottare invece un AV1 con prestazioni comparabili: AV1 (proprio come H.265) si comprime due volte meglio di WebM .

    Logo AV1 2018
    AV1 ha buone possibilità di diventare lo standard definitivo per i video sul web. (Credito immagine: Wikimedia.org) (Anteprima grande)

    In effetti, Apple attualmente utilizza il formato HEIF e HEVC (H.265) e tutte le foto e i video sull'ultimo iOS vengono salvati in questi formati, non JPEG. Sebbene HEIF e HEVC (H.265) non siano adeguatamente esposti al Web (ancora?), AV1 lo è e sta ottenendo il supporto del browser. Quindi aggiungere la sorgente AV1 nel tag <video> è ragionevole, poiché tutti i fornitori di browser sembrano essere d'accordo.

    Per ora, la codifica più utilizzata e supportata è H.264, servita da file MP4, quindi prima di servire il file, assicurati che i tuoi MP4 siano elaborati con una codifica multipass, sfocata con l'effetto frei0r iirblur (se applicabile) e I metadati di moov atom vengono spostati nella parte iniziale del file, mentre il tuo server accetta la pubblicazione di byte. Boris Schapira fornisce istruzioni esatte per FFmpeg per ottimizzare i video al massimo. Naturalmente, anche fornire il formato WebM in alternativa aiuterebbe.

    Devi iniziare a eseguire il rendering dei video più velocemente ma i file video sono ancora troppo grandi ? Ad esempio, ogni volta che hai un video di sfondo di grandi dimensioni su una pagina di destinazione? Una tecnica comune da utilizzare consiste nel mostrare prima il primo fotogramma come immagine fissa, oppure visualizzare un breve segmento di loop fortemente ottimizzato che potrebbe essere interpretato come parte del video, quindi, ogni volta che il video è sufficientemente bufferizzato, avviare la riproduzione il video vero e proprio. Doug Sillars ha scritto una guida dettagliata alle prestazioni dei video in background che potrebbe essere utile in questo caso. ( Grazie, Guy Podjarny! ).

    Per lo scenario precedente, potresti voler fornire immagini poster reattive . Per impostazione predefinita, gli elementi video consentono solo un'immagine come poster, il che non è necessariamente ottimale. Possiamo utilizzare Responsive Video Poster, una libreria JavaScript che ti consente di utilizzare immagini poster diverse per schermi diversi, aggiungendo anche una sovrapposizione di transizione e un controllo completo dello stile dei segnaposto video.

    La ricerca mostra che la qualità del flusso video influisce sul comportamento degli spettatori. Infatti, gli spettatori iniziano ad abbandonare il video se il ritardo di avvio supera i 2 secondi circa. Oltre tale punto, un aumento di 1 secondo del ritardo si traduce in un aumento di circa il 5,8% del tasso di abbandono. Quindi non sorprende che l'ora mediana di inizio del video sia 12,8 secondi, con il 40% dei video con almeno 1 stallo e il 20% almeno 2 secondi di riproduzione video bloccata. In effetti, gli stalli video sono inevitabili su 3G poiché i video vengono riprodotti più velocemente di quanto la rete possa fornire contenuti.

    Allora, qual è la soluzione? Di solito i dispositivi con schermo piccolo non sono in grado di gestire i 720p e i 1080p che stiamo servendo sul desktop. Secondo Doug Sillars, possiamo creare versioni più piccole dei nostri video e utilizzare Javascript per rilevare la fonte per schermi più piccoli per garantire una riproduzione veloce e fluida su questi dispositivi. In alternativa, possiamo utilizzare lo streaming video. I flussi video HLS forniranno un video di dimensioni adeguate al dispositivo, eliminando la necessità di creare video diversi per schermi diversi. Negozierà anche la velocità della rete e adatterà il bitrate video alla velocità della rete che stai utilizzando.

    Per evitare lo spreco di larghezza di banda, potremmo aggiungere la sorgente video solo per i dispositivi che effettivamente possono riprodurre bene il video. In alternativa, possiamo rimuovere del tutto l'attributo di riproduzione autoplay dal tag video e utilizzare JavaScript per inserire la autoplay per schermi più grandi. Inoltre, dobbiamo aggiungere preload="none" sul video per dire al browser di non scaricare nessuno dei file video fino a quando non ha effettivamente bisogno del file:

    <!-- Based on Doug Sillars's post. https://dougsillars.com/2020/01/06/hiding-videos-on-the-mbile-web/ --> <video preload="none" playsinline muted loop width="1920" height="1080" poster="poster.jpg"> <source src="video.webm" type="video/webm"> <source src="video.mp4" type="video/mp4"> </video>

    Quindi possiamo indirizzare specificamente i browser che supportano effettivamente AV1:

    <!-- Based on Doug Sillars's post. https://dougsillars.com/2020/01/06/hiding-videos-on-the-mbile-web/ --> <video preload="none" playsinline muted loop width="1920" height="1080" poster="poster.jpg"> <source src="video.av1.mp4" type="video/mp4; codecs=av01.0.05M.08"> <source src="video.hevc.mp4" type="video/mp4; codecs=hevc"> <source src="video.webm" type="video/webm"> <source src="video.mp4" type="video/mp4"> </video>

    Potremmo quindi aggiungere nuovamente l' autoplay oltre una certa soglia (es. 1000px):

    /* By Doug Sillars. https://dougsillars.com/2020/01/06/hiding-videos-on-the-mbile-web/ */ <script> window.onload = addAutoplay(); var videoLocation = document.getElementById("hero-video"); function addAutoplay() { if(window.innerWidth > 1000){ videoLocation.setAttribute("autoplay",""); }; } </script>
    Un grafico a barre che mostra piccoli tempi (ms) per dispositivo e velocità di rete, inclusi 3G, cavo, LTE e nativo su Alcatel 1X, Moto G, Moto G4, MotoE, Nexus 5 e OnePlus 5
    Numero di stalli per dispositivo e velocità di rete. I dispositivi più veloci su reti più veloci non hanno praticamente stalli. Secondo la ricerca di Doug Sillars. (Grande anteprima)

    Le prestazioni di riproduzione video sono una storia a sé stante e, se desideri approfondire i dettagli, dai un'occhiata a un'altra serie di Doug Sillars su The Current State of Video and Video Delivery Best Practices che include dettagli sulle metriche di consegna video , precaricamento, compressione e streaming video. Infine, puoi verificare quanto sarà lento o veloce il tuo streaming video con Stream or Not.

La guida completa di Zach Leatherman alle strategie di caricamento dei caratteri mostrata come un grafico della mappa mentale
La guida completa di Zach Leatherman alle strategie di caricamento dei caratteri offre una dozzina di opzioni per una migliore distribuzione dei caratteri Web.
  1. La consegna dei caratteri web è ottimizzata?
    La prima domanda che vale la pena porsi è se possiamo farla franca utilizzando i caratteri del sistema dell'interfaccia utente in primo luogo: dobbiamo solo assicurarci di ricontrollare che appaiano correttamente su varie piattaforme. In caso contrario, è molto probabile che i caratteri Web che stiamo servendo includano glifi e funzionalità e pesi extra che non vengono utilizzati. Possiamo chiedere alla nostra fonderia di tipi di sottoimpostare i caratteri Web o, se stiamo utilizzando caratteri open source, sottoimpostarli da soli con Glyphhanger o Fontsquirrel. Possiamo persino automatizzare l'intero flusso di lavoro con il sottocarattere di Peter Muller, uno strumento da riga di comando che analizza staticamente la tua pagina per generare i sottoinsiemi di caratteri Web più ottimali e quindi iniettarli nelle nostre pagine.

    Il supporto di WOFF2 è ottimo e possiamo utilizzare WOFF come fallback per i browser che non lo supportano, o forse i browser legacy potrebbero essere serviti come font di sistema. Esistono molte, molte, molte opzioni per il caricamento dei caratteri Web e possiamo scegliere una delle strategie della "Guida completa alle strategie di caricamento dei caratteri" di Zach Leatherman (snippet di codice disponibili anche come ricette di caricamento dei caratteri Web).

    Probabilmente le migliori opzioni da considerare oggi sono Critical FOFT con preload e il metodo "The Compromise". Entrambi utilizzano un rendering a due fasi per fornire i caratteri Web in più fasi: prima un piccolo supersottoinsieme necessario per eseguire il rendering della pagina in modo rapido e accurato con il carattere Web, quindi caricare il resto della famiglia in modo asincrono. La differenza è che la tecnica "The Compromise" carica il polyfill in modo asincrono solo se gli eventi di caricamento dei font non sono supportati, quindi non è necessario caricare il polyfill per impostazione predefinita. Hai bisogno di una vittoria veloce? Zach Leatherman ha un breve tutorial di 23 minuti e un case study per mettere in ordine i tuoi caratteri.

    In generale, potrebbe essere una buona idea utilizzare il suggerimento per la risorsa di preload per precaricare i caratteri, ma nel tuo markup includi i suggerimenti dopo il collegamento a CSS e JavaScript critici. Con preload , c'è un puzzle di priorità, quindi considera di iniettare elementi rel="preload" nel DOM appena prima degli script di blocco esterni. Secondo Andy Davies, "le risorse iniettate utilizzando uno script sono nascoste dal browser fino all'esecuzione dello script e possiamo utilizzare questo comportamento per ritardare quando il browser rileva il suggerimento di preload ". Altrimenti, il caricamento dei caratteri ti costerà nel primo tempo di rendering.

    Uno screenshot della diapositiva 93 che mostra due esempi di immagini con un titolo accanto che dice "Priorità delle metriche: precarica una per famiglia"
    Quando tutto è critico, niente è critico. precarica solo uno o un massimo di due font per famiglia. (Credito immagine: Zach Leatherman – diapositiva 93) (Anteprima grande)

    È una buona idea essere selettivi e scegliere i file che contano di più, ad esempio quelli che sono critici per il rendering o che ti aiuterebbero a evitare ridisposizioni di testo visibili e di disturbo. In generale, Zach consiglia di precaricare uno o due caratteri di ciascuna famiglia : ha anche senso ritardare il caricamento di alcuni caratteri se sono meno critici.

    È diventato abbastanza comune usare il valore local() (che si riferisce a un font locale per nome) quando si definisce una font-family di font nella regola @font-face :

     /* Warning! Not a good idea! */ @font-face { font-family: Open Sans; src: local('Open Sans Regular'), local('OpenSans-Regular'), url('opensans.woff2') format ('woff2'), url('opensans.woff') format('woff'); }

    L'idea è ragionevole: alcuni popolari font open source come Open Sans vengono preinstallati con alcuni driver o app, quindi se il font è disponibile localmente, il browser non ha bisogno di scaricare il font web e può visualizzare il font locale carattere immediatamente. Come ha osservato Bram Stein, "sebbene un font locale corrisponda al nome di un font web, molto probabilmente non è lo stesso font . Molti font web differiscono dalla loro versione" desktop ". Il testo potrebbe essere visualizzato in modo diverso, alcuni caratteri potrebbero cadere tornando ad altri tipi di carattere, le funzionalità OpenType potrebbero mancare del tutto o l'altezza della linea potrebbe essere diversa."

    Inoltre, poiché i caratteri tipografici si evolvono nel tempo, la versione installata localmente potrebbe essere molto diversa dal carattere Web, con caratteri molto diversi. Quindi, secondo Bram, è meglio non mischiare mai font e font web installati localmente nelle regole @font-face . Google Fonts ha seguito l'esempio disabilitando local() sui risultati CSS per tutti gli utenti, ad eccezione delle richieste Android per Roboto.

    A nessuno piace aspettare che il contenuto venga visualizzato. Con il descrittore CSS font-display , possiamo controllare il comportamento di caricamento dei caratteri e consentire la leggibilità del contenuto immediatamente (con font-display: optional ) o quasi immediatamente (con un timeout di 3 secondi, a condizione che il carattere venga scaricato correttamente — con font-display: swap ). (Beh, è ​​un po' più complicato di così.)

    Tuttavia, se desideri ridurre al minimo l'impatto dei ridisposizioni di testo, potremmo utilizzare l' API di caricamento dei caratteri (supportata in tutti i browser moderni). In particolare ciò significa che per ogni font, avremmo creato un oggetto FontFace , quindi proveremo a recuperarli tutti e solo successivamente applicarli alla pagina. In questo modo, raggruppiamo tutti i ridisegni caricando tutti i caratteri in modo asincrono, quindi passiamo dai caratteri di fallback al carattere Web esattamente una volta. Dai un'occhiata alla spiegazione di Zach, a partire dalle 32:15, e al frammento di codice):

    /* Load two web fonts using JavaScript */ /* Zach Leatherman: https://noti.st/zachleat/KNaZEg/the-five-whys-of-web-font-loading-performance#sWkN4u4 */ // Remove existing @font-face blocks // Create two let font = new FontFace("Noto Serif", /* ... */); let fontBold = new FontFace("Noto Serif, /* ... */); // Load two fonts let fonts = await Promise.all([ font.load(), fontBold.load() ]) // Group repaints and render both fonts at the same time! fonts.forEach(font => documents.fonts.add(font));
    /* Load two web fonts using JavaScript */ /* Zach Leatherman: https://noti.st/zachleat/KNaZEg/the-five-whys-of-web-font-loading-performance#sWkN4u4 */ // Remove existing @font-face blocks // Create two let font = new FontFace("Noto Serif", /* ... */); let fontBold = new FontFace("Noto Serif, /* ... */); // Load two fonts let fonts = await Promise.all([ font.load(), fontBold.load() ]) // Group repaints and render both fonts at the same time! fonts.forEach(font => documents.fonts.add(font));

    Per avviare un recupero molto precoce dei caratteri con l'API di caricamento dei caratteri in uso, Adrian Bece suggerisce di aggiungere uno spazio unificatore nbsp; nella parte superiore del body e nascondilo visivamente con aria-visibility: hidden e una classe .hidden :

    <body class="no-js"> <!-- ... Website content ... --> <div aria-visibility="hidden" class="hidden"> <!-- There is a non-breaking space here --> </div> <script> document.getElementsByTagName("body")[0].classList.remove("no-js"); </script> </body>
    <body class="no-js"> <!-- ... Website content ... --> <div aria-visibility="hidden" class="hidden"> <!-- There is a non-breaking space here --> </div> <script> document.getElementsByTagName("body")[0].classList.remove("no-js"); </script> </body>

    Questo va di pari passo con CSS che ha diverse famiglie di caratteri dichiarate per diversi stati di caricamento, con la modifica attivata dall'API di caricamento dei caratteri una volta che i caratteri sono stati caricati correttamente:

    body:not(.wf-merriweather--loaded):not(.no-js) { font-family: [fallback-system-font]; /* Fallback font styles */ } .wf-merriweather--loaded, .no-js { font-family: "[web-font-name]"; /* Webfont styles */ } /* Accessible hiding */ .hidden { position: absolute; overflow: hidden; clip: rect(0 0 0 0); height: 1px; width: 1px; margin: -1px; padding: 0; border: 0; }
    body:not(.wf-merriweather--loaded):not(.no-js) { font-family: [fallback-system-font]; /* Fallback font styles */ } .wf-merriweather--loaded, .no-js { font-family: "[web-font-name]"; /* Webfont styles */ } /* Accessible hiding */ .hidden { position: absolute; overflow: hidden; clip: rect(0 0 0 0); height: 1px; width: 1px; margin: -1px; padding: 0; border: 0; }

    Se ti sei mai chiesto perché, nonostante tutte le tue ottimizzazioni, Lighthouse suggerisce ancora di eliminare le risorse di blocco del rendering (font), nello stesso articolo Adrian Bece fornisce alcune tecniche per rendere felice Lighthouse, insieme a un Gatsby Omni Font Loader, un font asincrono performante caricamento e plug-in per la gestione di Flash Of Unstyled Text (FOUT) per Gatsby.

    Ora, molti di noi potrebbero utilizzare una CDN o un host di terze parti da cui caricare i caratteri Web. In generale, è sempre meglio ospitare autonomamente tutte le tue risorse statiche, se possibile, quindi considera l'utilizzo di google-webfonts-helper, un modo semplice per ospitare automaticamente Google Fonts. E se non è possibile, puoi forse delegare i file di Google Font tramite l'origine della pagina.

    Vale la pena notare, tuttavia, che Google sta facendo un bel po' di lavoro fuori dagli schemi, quindi un server potrebbe aver bisogno di un po' di ritocco per evitare ritardi ( grazie, Barry! )

    Questo è abbastanza importante soprattutto perché da Chrome v86 (rilasciato a ottobre 2020), le risorse cross-site come i caratteri non possono più essere condivise sulla stessa CDN, a causa della cache del browser partizionata. Questo comportamento è stato un'impostazione predefinita in Safari per anni.

    Ma se non è affatto possibile, c'è un modo per ottenere i caratteri Google più veloci possibili con lo snippet di Harry Roberts:

    <!-- By Harry Roberts. https://csswizardry.com/2020/05/the-fastest-google-fonts/ - 1. Preemptively warm up the fonts' origin. - 2. Initiate a high-priority, asynchronous fetch for the CSS file. Works in - most modern browsers. - 3. Initiate a low-priority, asynchronous fetch that gets applied to the page - only after it's arrived. Works in all browsers with JavaScript enabled. - 4. In the unlikely event that a visitor has intentionally disabled - JavaScript, fall back to the original method. The good news is that, - although this is a render-blocking request, it can still make use of the - preconnect which makes it marginally faster than the default. --> <!-- [1] --> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> <!-- [2] --> <link rel="preload" as="style" href="$CSS&display=swap" /> <!-- [3] --> <link rel="stylesheet" href="$CSS&display=swap" media="print" onload="this.media='all'" /> <!-- [4] --> <noscript> <link rel="stylesheet" href="$CSS&display=swap" /> </noscript>

    La strategia di Harry è di riscaldare preventivamente l'origine dei caratteri prima. Quindi avviamo un recupero asincrono ad alta priorità per il file CSS. Successivamente, avviamo un recupero asincrono a bassa priorità che viene applicato alla pagina solo dopo che è arrivata (con un trucco del foglio di stile di stampa). Infine, se JavaScript non è supportato, torniamo al metodo originale.

    Ah, parlando di Google Fonts: puoi ridurre fino al 90% la dimensione delle richieste di Google Fonts dichiarando solo i caratteri che ti servono con &text . Inoltre, il supporto per la visualizzazione dei caratteri è stato aggiunto di recente anche a Google Fonts, quindi possiamo usarlo immediatamente.

    Una breve parola di cautela però. Se utilizzi font-display: optional , potrebbe non essere ottimale utilizzare anche il preload in quanto attiverà in anticipo la richiesta di font Web (causando una congestione della rete se hai altre risorse di percorso critiche che devono essere recuperate). Usa preconnect per richieste di font tra origini più veloci, ma fai attenzione con il preload poiché il precaricamento dei font da un'origine diversa comporterà conflitti di rete. Tutte queste tecniche sono trattate nelle ricette di caricamento dei caratteri Web di Zach.

    D'altra parte, potrebbe essere una buona idea disattivare i caratteri Web (o almeno il rendering della seconda fase) se l'utente ha abilitato Riduci movimento nelle preferenze di accessibilità o ha optato per la modalità Risparmio dati (vedi intestazione Save-Data ) o quando l'utente ha una connettività lenta (tramite Network Information API).

    Possiamo anche utilizzare la query multimediale CSS prefers-reduced-data per non definire le dichiarazioni dei caratteri se l'utente ha attivato la modalità di salvataggio dei dati (ci sono anche altri casi d'uso). La query multimediale mostrerebbe sostanzialmente se l'intestazione della richiesta Save-Data dall'estensione HTTP Hint client è attivata/disattivata per consentire l'utilizzo con CSS. Attualmente supportato solo in Chrome e Edge dietro una bandiera.

    Metrica? Per misurare le prestazioni di caricamento dei caratteri Web, considera la metrica Tutto il testo visibile (il momento in cui tutti i caratteri sono stati caricati e tutto il contenuto viene visualizzato nei caratteri Web), Tempo per il corsivo reale e Conteggio riflusso dei caratteri Web dopo il primo rendering. Ovviamente, più basse sono entrambe le metriche, migliori saranno le prestazioni.

    Che dire dei caratteri variabili , potresti chiedere? È importante notare che i caratteri variabili potrebbero richiedere una considerazione significativa delle prestazioni. Ci danno uno spazio di progettazione molto più ampio per le scelte tipografiche, ma viene al costo di una singola richiesta seriale rispetto a un numero di richieste di file individuali.

    Sebbene i caratteri variabili riducano drasticamente le dimensioni complessive dei file di caratteri combinati, quella singola richiesta potrebbe essere lenta, bloccando il rendering di tutto il contenuto di una pagina. Quindi il sottoinsieme e la divisione del carattere in set di caratteri sono ancora importanti. Tra i lati positivi, tuttavia, con un carattere variabile in atto, otterremo esattamente un reflow per impostazione predefinita, quindi non sarà richiesto JavaScript per raggruppare i ridisegni.

    Ora, cosa renderebbe allora una strategia di caricamento dei font web a prova di proiettile ? Sottoimposta i caratteri e preparali per il rendering in 2 fasi, dichiarali con un descrittore font-display , utilizza l'API di caricamento dei caratteri per raggruppare i ridisegni e archiviare i caratteri nella cache di un lavoratore del servizio permanente. Alla prima visita, iniettare il precaricamento degli script appena prima degli script esterni di blocco. Se necessario, potresti ricorrere a Font Face Observer di Bram Stein. E se sei interessato a misurare le prestazioni del caricamento dei caratteri, Andreas Marschke esplora il monitoraggio delle prestazioni con l'API dei caratteri e l'API UserTiming.

    Infine, non dimenticare di includere unicode-range per scomporre un carattere grande in caratteri più piccoli specifici della lingua e utilizzare il corrispettivo dello stile dei caratteri di Monica Dinculescu per ridurre al minimo uno spostamento stridente nel layout, a causa delle discrepanze di dimensioni tra il fallback e il caratteri web.

    In alternativa, per emulare un font web per un font di fallback, possiamo usare i descrittori @font-face per sovrascrivere le metriche dei font (demo, abilitato in Chrome 87). (Si noti che le regolazioni sono complicate con pile di caratteri complicate.)

    Il futuro sembra luminoso? Con l'arricchimento progressivo dei caratteri, alla fine potremmo essere in grado di "scaricare solo la parte richiesta del carattere su una determinata pagina e, per le successive richieste di quel carattere, "rattoppare" dinamicamente il download originale con set aggiuntivi di glifi come richiesto nella pagina successiva visualizzazioni", come spiega Jason Pamental. La demo di trasferimento incrementale è già disponibile ed è in lavorazione.

Costruisci ottimizzazioni

  1. Abbiamo definito le nostre priorità?
    È una buona idea sapere prima con cosa hai a che fare. Esegui un inventario di tutte le tue risorse (JavaScript, immagini, caratteri, script di terze parti e moduli "costosi" sulla pagina, come caroselli, infografiche complesse e contenuti multimediali) e suddividili in gruppi.

    Imposta un foglio di calcolo . Definisci l'esperienza di base di base per i browser legacy (ovvero il contenuto di base completamente accessibile), l'esperienza avanzata per i browser abilitati (ovvero un'esperienza completa e arricchita) e gli extra (risorse che non sono assolutamente necessarie e possono essere caricate in modo pigro, come font web, stili non necessari, script di carosello, lettori video, widget di social media, immagini di grandi dimensioni). Anni fa, abbiamo pubblicato un articolo su "Improving Smashing Magazine's Performance", che descrive questo approccio in dettaglio.

    Quando ottimizziamo le prestazioni, dobbiamo riflettere le nostre priorità. Carica immediatamente l' esperienza principale , poi i miglioramenti e poi gli extra .

  2. Utilizzi moduli JavaScript nativi in ​​produzione?
    Ricordi la buona vecchia tecnica del taglio della senape per inviare l'esperienza di base ai browser legacy e un'esperienza migliorata ai browser moderni? Una variante aggiornata della tecnica potrebbe utilizzare ES2017+ <script type="module"> , noto anche come pattern module/nomodule (introdotto anche da Jeremy Wagner come servizio differenziale ).

    L'idea è di compilare e servire due bundle JavaScript separati : la build "normale", quella con Babel-transforms e polyfill e servirli solo ai browser legacy che ne hanno effettivamente bisogno, e un altro bundle (stessa funzionalità) che non ha trasformazioni o poliriempimenti.

    Di conseguenza, aiutiamo a ridurre il blocco del thread principale riducendo la quantità di script che il browser deve elaborare. Jeremy Wagner ha pubblicato un articolo completo sul servizio differenziale e su come configurarlo nella pipeline di compilazione, dall'impostazione di Babel, alle modifiche che dovrai apportare in Webpack, nonché ai vantaggi di fare tutto questo lavoro.

    Gli script dei moduli JavaScript nativi sono posticipati per impostazione predefinita, quindi mentre è in corso l'analisi HTML, il browser scaricherà il modulo principale.

    Un esempio che mostra come i moduli JavaScript nativi vengono differiti per impostazione predefinita
    I moduli JavaScript nativi sono posticipati per impostazione predefinita. Praticamente tutto sui moduli JavaScript nativi. (Grande anteprima)

    Una nota di avvertimento però: il pattern module/nomodule può ritorcersi contro alcuni client, quindi potresti prendere in considerazione una soluzione alternativa: il pattern di servizio differenziale meno rischioso di Jeremy che, tuttavia, elude lo scanner di precaricamento, che potrebbe influire sulle prestazioni in modi che non si potrebbero anticipare. ( grazie, Jeremy! )

    In effetti, Rollup supporta i moduli come formato di output, quindi possiamo sia raggruppare il codice che distribuire i moduli in produzione. Parcel ha il supporto del modulo in Parcel 2. Per Webpack, module-nomodule-plugin automatizza la generazione di script module/nomodule.

    Nota : vale la pena affermare che il rilevamento delle funzionalità da solo non è sufficiente per prendere una decisione informata sul carico utile da spedire a quel browser. Di per sé, non possiamo dedurre la capacità del dispositivo dalla versione del browser. Ad esempio, i telefoni Android economici nei paesi in via di sviluppo eseguono principalmente Chrome e ridurranno la senape nonostante la memoria limitata e le capacità della CPU.

    Alla fine, utilizzando l'intestazione dei suggerimenti del client di memoria del dispositivo, saremo in grado di indirizzare i dispositivi di fascia bassa in modo più affidabile. Al momento della scrittura, l'intestazione è supportata solo in Blink (vale per i suggerimenti del cliente in generale). Poiché Device Memory ha anche un'API JavaScript disponibile in Chrome, un'opzione potrebbe essere quella di rilevare funzionalità in base all'API e tornare al pattern module/nomodule se non è supportato ( grazie, Yoav! ).

  3. Stai usando lo scuotimento degli alberi, il sollevamento del cannocchiale e la suddivisione del codice?
    Il tree-shaking è un modo per ripulire il processo di compilazione includendo solo il codice effettivamente utilizzato nella produzione ed eliminando le importazioni inutilizzate in Webpack. Con Webpack e Rollup, abbiamo anche il sollevamento dell'ambito che consente a entrambi gli strumenti di rilevare dove il concatenamento di import può essere appiattito e convertito in una funzione inline senza compromettere il codice. Con Webpack, possiamo anche utilizzare JSON Tree Shaking.

    La suddivisione del codice è un'altra funzionalità di Webpack che suddivide la base di codice in "blocchi" caricati su richiesta. Non tutto JavaScript deve essere scaricato, analizzato e compilato subito. Una volta definiti i punti di divisione nel codice, Webpack può occuparsi delle dipendenze e dei file prodotti. Ti consente di mantenere piccolo il download iniziale e di richiedere il codice su richiesta quando richiesto dall'applicazione. Alexander Kondrov ha una fantastica introduzione alla divisione del codice con Webpack e React.

    Prendi in considerazione l'utilizzo di preload-webpack-plugin che prende le rotte suddivise in codice e quindi richiede al browser di precaricarle utilizzando <link rel="preload"> o <link rel="prefetch"> . Le direttive inline di Webpack danno anche un certo controllo su preload / prefetch . (Fai attenzione ai problemi di priorità.)

    Dove definire i punti di divisione? Tracciando quali blocchi di CSS/JavaScript vengono utilizzati e quali non vengono utilizzati. Umar Hansa spiega come utilizzare la copertura del codice di Devtools per ottenerlo.

    Quando si tratta di applicazioni a pagina singola, è necessario del tempo per inizializzare l'app prima di poter eseguire il rendering della pagina. La tua impostazione richiederà la tua soluzione personalizzata, ma potresti fare attenzione a moduli e tecniche per accelerare il tempo di rendering iniziale. Ad esempio, ecco come eseguire il debug delle prestazioni di React ed eliminare i problemi comuni di prestazioni di React, ed ecco come migliorare le prestazioni in Angular. In generale, la maggior parte dei problemi di prestazioni deriva dall'avvio iniziale dell'app.

    Quindi, qual è il modo migliore per dividere il codice in modo aggressivo, ma non troppo aggressivo? Secondo Phil Walton, "oltre alla suddivisione del codice tramite importazioni dinamiche, [potremmo] anche utilizzare la suddivisione del codice a livello di pacchetto , in cui ogni modulo del nodo importato viene inserito in un blocco in base al nome del pacchetto". Phil fornisce anche un tutorial su come costruirlo.

  4. Possiamo migliorare l'output di Webpack?
    Poiché Webpack è spesso considerato misterioso, ci sono molti plug-in Webpack che possono tornare utili per ridurre ulteriormente l'output di Webpack. Di seguito sono riportati alcuni di quelli più oscuri che potrebbero richiedere un po' più di attenzione.

    Uno di quelli interessanti viene dal thread di Ivan Akulov. Immagina di avere una funzione che chiami una volta, memorizzi il suo risultato in una variabile e quindi non usi quella variabile. Lo scuotimento dell'albero rimuoverà la variabile, ma non la funzione, perché potrebbe essere utilizzata diversamente. Tuttavia, se la funzione non viene utilizzata da nessuna parte, potresti volerla rimuovere. Per fare ciò, anteponi la chiamata alla funzione con /*#__PURE__*/ che è supportata da Uglify e Terser — fatto!

    Uno screenshot del codice JS in un editor che mostra come è possibile utilizzare la funzione PURE
    Per rimuovere una tale funzione quando il suo risultato non viene utilizzato, anteporre la chiamata alla funzione con /*#__PURE__*/ . Via Ivan Akulov.(Grande anteprima)

    Ecco alcuni degli altri strumenti che Ivan consiglia:

    • purgecss-webpack-plugin rimuove le classi non utilizzate, specialmente quando si utilizza Bootstrap o Tailwind.
    • Abilita optimization.splitChunks: 'all' con split-chunks-plugin. Ciò renderebbe webpack automaticamente diviso in codice i tuoi bundle di voci per una migliore memorizzazione nella cache.
    • Imposta optimization.runtimeChunk: true . Ciò sposterebbe il runtime del webpack in un blocco separato e migliorerebbe anche la memorizzazione nella cache.
    • google-fonts-webpack-plugin scarica i file dei caratteri, così puoi servirli dal tuo server.
    • workbox-webpack-plugin ti consente di generare un service worker con una configurazione di precaching per tutte le tue risorse webpack. Inoltre, controlla i pacchetti Service Worker, una guida completa di moduli che potrebbero essere applicati immediatamente. Oppure usa preload-webpack-plugin per generare preload / prefetch per tutti i blocchi JavaScript.
    • speed-measure-webpack-plugin misura la velocità di compilazione del tuo webpack, fornendo informazioni dettagliate su quali fasi del processo di compilazione richiedono più tempo.
    • duplicate-package-checker-webpack-plugin avverte quando il pacchetto contiene più versioni dello stesso pacchetto.
    • Usa l'isolamento dell'ambito e abbrevia i nomi delle classi CSS in modo dinamico al momento della compilazione.

Uno screenshot di un terminale che mostra come il caricatore di webpack denominato caricatore-responsivo può essere utilizzato per aiutarti a generare immagini reattive fuori dagli schemi
Velocizzare le tue immagini è servire immagini più piccole su schermi più piccoli. Con caricatore reattivo. Via Ivan Akulov. (Grande anteprima)
  1. Puoi scaricare JavaScript in un Web Worker?
    Per ridurre l'impatto negativo su Time-to-Interactive, potrebbe essere una buona idea esaminare l'offload di JavaScript pesante in un Web Worker.

    Man mano che la base di codice continua a crescere, i colli di bottiglia delle prestazioni dell'interfaccia utente verranno visualizzati, rallentando l'esperienza dell'utente. Questo perché le operazioni DOM vengono eseguite insieme al tuo JavaScript sul thread principale. Con i web worker, possiamo spostare queste costose operazioni in un processo in background in esecuzione su un thread diverso. I casi d'uso tipici per i lavoratori Web sono il precaricamento dei dati e le app Web progressive per caricare e archiviare alcuni dati in anticipo in modo da poterli utilizzare in seguito quando necessario. E potresti usare Comlink per semplificare la comunicazione tra la pagina principale e il lavoratore. Ancora un po' di lavoro da fare, ma ci stiamo arrivando.

    Ci sono alcuni casi di studio interessanti sui web worker che mostrano diversi approcci per spostare la logica del framework e delle app ai web worker. La conclusione: in generale, ci sono ancora alcune sfide, ma ci sono già dei buoni casi d'uso ( grazie, Ivan Akulov! ).

    A partire da Chrome 80, è stata lanciata una nuova modalità per i web worker con i vantaggi in termini di prestazioni dei moduli JavaScript, denominata module worker. Possiamo modificare il caricamento e l'esecuzione degli script in modo che corrispondano allo script type="module" , inoltre possiamo anche utilizzare le importazioni dinamiche per il caricamento lento del codice senza bloccare l'esecuzione del lavoratore.

    Come iniziare? Ecco alcune risorse che vale la pena esaminare:

    • Surma ha pubblicato un'eccellente guida su come eseguire JavaScript dal thread principale del browser e anche Quando dovresti usare i Web Workers?
    • Inoltre, controlla i discorsi di Surma sull'architettura del thread principale.
    • A Quest to Guarantee Responsiveness di Shubhie Panicker e Jason Miller forniscono informazioni dettagliate su come utilizzare i web worker e quando evitarli.
    • Uscire dagli utenti: meno lavoro con i lavoratori Web mette in evidenza modelli utili per lavorare con i lavoratori Web, modi efficaci per comunicare tra lavoratori, gestire l'elaborazione di dati complessi fuori dal thread principale, testarli ed eseguirne il debug.
    • Workerize consente di spostare un modulo in un Web Worker, riflettendo automaticamente le funzioni esportate come proxy asincroni.
    • Se stai usando Webpack, puoi usare workerize-loader. In alternativa, puoi usare anche worker-plugin.
    Codice nel DOM mostrato a sinistra come esempio di cosa usare ed evitare quando si utilizzano i web worker
    Usa i web worker quando il codice si blocca per molto tempo, ma evitali quando ti affidi al DOM, gestisci la risposta all'input e hai bisogno di un ritardo minimo. (via Addy Osmani) (Anteprima grande)

    Nota che i Web Worker non hanno accesso al DOM perché il DOM non è "thread-safe" e il codice che eseguono deve essere contenuto in un file separato.

  2. Puoi scaricare "percorsi caldi" su WebAssembly?
    Potremmo scaricare compiti computazionalmente pesanti su WebAssembly ( WASM ), un formato di istruzione binaria, progettato come destinazione portatile per la compilazione di linguaggi di alto livello come C/C++/Rust. Il supporto del browser è notevole e di recente è diventato praticabile poiché le chiamate di funzione tra JavaScript e WASM stanno diventando più veloci. Inoltre, è persino supportato sull'edge cloud di Fastly.

    Naturalmente, WebAssembly non dovrebbe sostituire JavaScript, ma può integrarlo nei casi in cui si notano problemi di CPU. Per la maggior parte delle app Web, JavaScript è più adatto e WebAssembly è utilizzato al meglio per app Web ad alta intensità di calcolo , come i giochi.

    Se desideri saperne di più su WebAssembly:

    • Lin Clark ha scritto una serie completa per WebAssembly e Milica Mihajlija fornisce una panoramica generale su come eseguire codice nativo nel browser, perché potresti volerlo fare e cosa significa tutto questo per JavaScript e il futuro dello sviluppo web.
    • Come abbiamo utilizzato WebAssembly per velocizzare la nostra app Web di 20 volte (Case Study) evidenzia un caso di studio su come i calcoli JavaScript lenti sono stati sostituiti con WebAssembly compilati e hanno apportato miglioramenti significativi alle prestazioni.
    • Patrick Hamann ha parlato del ruolo crescente di WebAssembly e sta sfatando alcuni miti sul WebAssembly, ne esplora le sfide e oggi possiamo usarlo praticamente nelle applicazioni.
    • Google Codelabs fornisce un'introduzione a WebAssembly, un corso di 60 minuti in cui imparerai come prendere il codice nativo in C e compilarlo in WebAssembly, quindi chiamarlo direttamente da JavaScript.
    • Alex Danilo ha spiegato WebAssembly e come funziona durante il suo colloquio di Google I/O. Inoltre, Benedek Gagyi ha condiviso un caso di studio pratico su WebAssembly, in particolare su come il team lo utilizza come formato di output per la base di codice C++ su iOS, Android e il sito Web.

    Non sei ancora sicuro di quando utilizzare Web Worker, Web Assembly, stream o forse l'API JavaScript WebGL per accedere alla GPU? Accelerare JavaScript è una guida breve ma utile che spiega quando usare cosa e perché, anche con un diagramma di flusso pratico e molte risorse utili.

Un'illustrazione di C++, C o Rust mostrata a sinistra con una freccia che mostra un browser che include binari WASM aggiunti a JavaScript, CSS e HTML
Milica Mihajlija fornisce una panoramica generale di come funziona WebAssembly e perché è utile. (Grande anteprima)
  1. Serviamo codice legacy solo per browser legacy?
    Poiché ES2017 è notevolmente ben supportato nei browser moderni, possiamo utilizzare babelEsmPlugin per trasferire solo le funzionalità ES2017+ non supportate dai browser moderni a cui ti rivolgi.

    Houssein Djirdeh e Jason Miller hanno recentemente pubblicato una guida completa su come trasporre e servire JavaScript moderno e legacy, entrando nei dettagli per farlo funzionare con Webpack e Rollup e gli strumenti necessari. Puoi anche stimare la quantità di JavaScript che puoi eliminare dal tuo sito o dagli app bundle.

    I moduli JavaScript sono supportati in tutti i principali browser, quindi usa script type="module" per consentire ai browser con supporto del modulo ES di caricare il file, mentre i browser meno recenti potrebbero caricare build legacy con script nomodule .

    In questi giorni possiamo scrivere JavaScript basato su moduli che viene eseguito in modo nativo nel browser, senza transpiler o bundler. L'intestazione <link rel="modulepreload"> fornisce un modo per avviare il caricamento anticipato (e ad alta priorità) degli script dei moduli. Fondamentalmente, è un modo ingegnoso per aiutare a massimizzare l'utilizzo della larghezza di banda, dicendo al browser cosa deve recuperare in modo che non sia bloccato con nulla da fare durante quei lunghi viaggi di andata e ritorno. Inoltre, Jake Archibald ha pubblicato un articolo dettagliato con trucchi e cose da tenere a mente con i moduli ES che vale la pena leggere.

Gli script inline vengono posticipati fino al blocco degli script esterni e non vengono eseguiti gli script inline
Jake Archibald ha pubblicato un articolo dettagliato con trucchi e cose da tenere a mente con i moduli ES, ad esempio gli script inline vengono posticipati fino al blocco degli script esterni e gli script inline vengono eseguiti. (Grande anteprima)
  1. Identifica e riscrivi il codice legacy con il disaccoppiamento incrementale .
    I progetti di lunga durata hanno la tendenza a raccogliere polvere e codice datato. Rivedi le tue dipendenze e valuta quanto tempo sarebbe necessario per refactoring o riscrivere il codice legacy che ha causato problemi ultimamente. Naturalmente, è sempre una grande impresa, ma una volta che conosci l'impatto del codice legacy, potresti iniziare con il disaccoppiamento incrementale.

    Innanzitutto, imposta le metriche che tengono traccia se il rapporto delle chiamate di codice legacy rimane costante o diminuisce, non aumenta. Scoraggia pubblicamente il team dall'usare la libreria e assicurati che l'elemento della configurazione avvisi gli sviluppatori se viene utilizzata nelle richieste pull. polyfills potrebbe aiutare la transizione dal codice legacy alla base di codice riscritta che utilizza le funzionalità standard del browser.

  2. Identifica e rimuovi CSS/JS inutilizzati .
    La copertura del codice CSS e JavaScript in Chrome ti consente di sapere quale codice è stato eseguito/applicato e quale no. Puoi iniziare a registrare la copertura, eseguire azioni su una pagina e quindi esplorare i risultati della copertura del codice. Dopo aver rilevato il codice inutilizzato, trova quei moduli e carica lazy con import() (vedi l'intero thread). Quindi ripeti il ​​profilo di copertura e verifica che ora stia inviando meno codice al caricamento iniziale.

    Puoi utilizzare Puppeteer per raccogliere a livello di codice la copertura. Chrome ti consente anche di esportare i risultati della copertura del codice. Come ha notato Andy Davies, potresti voler raccogliere la copertura del codice sia per i browser moderni che per quelli legacy.

    Ci sono molti altri casi d'uso e strumenti per Puppetter che potrebbero richiedere un po' più di esposizione:

    • Casi d'uso per Burattinaio, come, ad esempio, la differenziazione visiva automatica o il monitoraggio di CSS inutilizzati con ogni build,
    • Ricette per performance web con Burattinaio,
    • Strumenti utili per la registrazione e la generazione di script Pupeeteer e Playwright,
    • Inoltre, puoi persino registrare i test direttamente in DevTools,
    • Panoramica completa di Puppeteer di Nitay Neeman, con esempi e casi d'uso.
    Uno screenshot del Pupeteer Recorder a sinistra e uno screenshot Puppeteer Sandbox mostrato a destra
    Possiamo utilizzare Puppeteer Recorder e Puppeteer Sandbox per registrare l'interazione del browser e generare script Puppeteer e Playwright. (Grande anteprima)

    Inoltre, purgecss, UnCSS ed Helium possono aiutarti a rimuovere gli stili inutilizzati dai CSS. E se non sei sicuro che un pezzo di codice sospetto sia usato da qualche parte, puoi seguire il consiglio di Harry Roberts: crea una GIF trasparente 1×1px per una classe particolare e rilasciala in una directory dead/ , ad esempio /assets/img/dead/comments.gif .

    Dopodiché, imposti quell'immagine specifica come sfondo sul selettore corrispondente nel tuo CSS, siediti e attendi qualche mese se il file apparirà nei tuoi registri. Se non ci sono voci, nessuno ha avuto quel componente legacy visualizzato sul proprio schermo: probabilmente puoi andare avanti ed eliminarlo tutto.

    Per il dipartimento I-feel-adventurous , potresti persino automatizzare la raccolta di CSS inutilizzati attraverso un insieme di pagine monitorando DevTools usando DevTools.

Tabella di confronto Webpack
Nel suo articolo, Benedikt Rotsch's ha mostrato che un passaggio da Moment.js a date-fns potrebbe radere circa 300 ms per la prima vernice su 3G e un telefono cellulare di fascia bassa. (Grande anteprima)
  1. Taglia le dimensioni dei tuoi bundle JavaScript.
    Come ha notato Addy Osmani, c'è un'alta probabilità che tu stia inviando librerie JavaScript complete quando ti serve solo una frazione, insieme a polyfill datati per i browser che non ne hanno bisogno o semplicemente duplicano il codice. Per evitare il sovraccarico, prendi in considerazione l'utilizzo di webpack-libs-optimizations che rimuove i metodi e i polyfill inutilizzati durante il processo di compilazione.

    Controlla e rivedi i polyfill che stai inviando ai browser legacy e ai browser moderni e sii più strategico al riguardo. Dai un'occhiata a polyfill.io che è un servizio che accetta una richiesta per un insieme di funzionalità del browser e restituisce solo i polyfill necessari al browser richiedente.

    Aggiungi anche il controllo dei pacchetti al tuo normale flusso di lavoro. Potrebbero esserci alcune alternative leggere alle librerie pesanti che hai aggiunto anni fa, ad esempio Moment.js (ora fuori produzione) potrebbe essere sostituito con:

    • API di internazionalizzazione nativa,
    • Day.js con un'API e modelli Moment.js familiari,
    • date-fns o
    • Luxon.
    • Puoi anche utilizzare Skypack Discover che combina i consigli sui pacchetti sottoposti a revisione umana con una ricerca incentrata sulla qualità.

    La ricerca di Benedikt Rotsch ha mostrato che un passaggio da Moment.js a date-fns potrebbe ridurre di circa 300 ms per la prima vernice su 3G e un telefono cellulare di fascia bassa.

    Per il controllo del pacchetto, Bundlephobia potrebbe aiutare a trovare il costo dell'aggiunta di un pacchetto npm al tuo pacchetto. size-limit estende il controllo delle dimensioni del pacchetto di base con dettagli sul tempo di esecuzione di JavaScript. Puoi anche integrare questi costi con un audit personalizzato del faro. Questo vale anche per i framework. Rimuovendo o tagliando l'adattatore Vue MDC (Component Components for Vue), gli stili scendono da 194 KB a 10 KB.

    Esistono molti altri strumenti per aiutarti a prendere una decisione informata sull'impatto delle tue dipendenze e alternative praticabili:

    • webpack-bundle-analyzer
    • Esplora mappa di origine
    • Fagotto amico
    • Fobia del fascio
    • L'analisi di Webpack mostra perché un modulo specifico è incluso nel pacchetto.
    • bundle-wizard crea anche una mappa delle dipendenze per l'intera pagina.
    • Plugin dimensione Webpack
    • Costo di importazione per codice visivo

    In alternativa alla spedizione dell'intero framework, puoi ritagliare il tuo framework e compilarlo in un bundle JavaScript grezzo che non richiede codice aggiuntivo. Svelte lo fa, così come il plug-in Rawact Babel che trasferisce i componenti React.js alle operazioni DOM native in fase di compilazione. Come mai? Bene, come spiegano i manutentori, "react-dom include codice per ogni possibile componente/HTMLElement di cui è possibile eseguire il rendering, incluso il codice per il rendering incrementale, la pianificazione, la gestione degli eventi, ecc. Ma ci sono applicazioni che non necessitano di tutte queste funzionalità (inizialmente caricamento della pagina). Per tali applicazioni, potrebbe avere senso utilizzare operazioni DOM native per creare l'interfaccia utente interattiva."

size-limit fornisce un controllo di base della dimensione del pacchetto con dettagli anche sul tempo di esecuzione di JavaScript
size-limit fornisce un controllo di base della dimensione del pacchetto con dettagli anche sul tempo di esecuzione di JavaScript. (Grande anteprima)
  1. Usiamo l'idratazione parziale?
    Con la quantità di JavaScript utilizzata nelle applicazioni, dobbiamo trovare il modo di inviare il meno possibile al client. Un modo per farlo - e l'abbiamo già brevemente trattato - è con l'idratazione parziale. L'idea è abbastanza semplice: invece di eseguire SSR e quindi inviare l'intera app al client, solo piccoli frammenti del JavaScript dell'app verrebbero inviati al client e quindi idratati. Possiamo pensarlo come più piccole app React con più radici di rendering su un sito Web altrimenti statico.

    Nell'articolo "Il caso dell'idratazione parziale (con Next e Preact)", Lukas Bombach spiega come il team dietro Welt.de, una delle testate giornalistiche in Germania, abbia ottenuto prestazioni migliori con l'idratazione parziale. Puoi anche controllare il repository GitHub successivo con prestazioni eccellenti con spiegazioni e frammenti di codice.

    Potresti anche considerare opzioni alternative:

    • idratazione parziale con Preact ed Eleventy,
    • idratazione progressiva nel repository React GitHub,
    • lazy-idratazione in Vue.js (repo GitHub),
    • Importa su modello di interazione per caricare in modo lento le risorse non critiche (ad es. componenti, incorporamenti) quando un utente interagisce con l'interfaccia utente che ne ha bisogno.

    Jason Miller ha pubblicato demo di lavoro su come implementare l'idratazione progressiva con React, quindi puoi usarle subito: demo 1, demo 2, demo 3 (disponibile anche su GitHub). Inoltre, puoi esaminare la libreria dei componenti di react-prerendering.

    +485 KB di JavaScript su loadshare() in Google Docs
    L'importazione all'interazione per il codice proprietario deve essere eseguita solo se non sei in grado di precaricare le risorse prima dell'interazione. (Grande anteprima)
  2. Abbiamo ottimizzato la strategia per React/SPA?
    Stai lottando con le prestazioni della tua applicazione a pagina singola? Jeremy Wagner ha esplorato l'impatto delle prestazioni del framework lato client su una varietà di dispositivi, evidenziando alcune delle implicazioni e delle linee guida di cui potremmo voler essere consapevoli quando ne utilizziamo uno.

    Di conseguenza, ecco una strategia SPA che Jeremy suggerisce di utilizzare per il framework React (ma non dovrebbe cambiare in modo significativo per altri framework):

    • Quando possibile, rifattorizzare i componenti con stato come componenti senza stato .
    • Quando possibile, eseguire il prerendering dei componenti stateless per ridurre al minimo i tempi di risposta del server. Rendering solo sul server.
    • Per i componenti con stato con interattività semplice, prendi in considerazione il prerendering o il rendering del server di quel componente e sostituisci la sua interattività con listener di eventi indipendenti dal framework .
    • Se devi idratare i componenti con stato sul client, usa l'idratazione pigra sulla visibilità o sull'interazione.
    • Per i componenti pigramente idratati, pianifica la loro idratazione durante il tempo di inattività del thread principale con requestIdleCallback .

    Ci sono alcune altre strategie che potresti voler perseguire o rivedere:

    • Considerazioni sulle prestazioni per CSS-in-JS nelle app React
    • Riduci le dimensioni del pacchetto Next.js caricando i polyfill solo quando necessario, utilizzando le importazioni dinamiche e l'idratazione pigra.
    • Segreti di JavaScript: una storia di React, ottimizzazione delle prestazioni e multi-threading, una lunga serie in 7 parti sul miglioramento delle sfide dell'interfaccia utente con React,
    • Come misurare le prestazioni di React e come profilare le applicazioni React.
    • Costruire animazioni Web mobile-first in React, un fantastico discorso di Alex Holachek, insieme a diapositive e repository GitHub ( grazie per il suggerimento, Addy! ).
    • webpack-libs-optimizations è un fantastico repository GitHub con molte utili ottimizzazioni relative alle prestazioni specifiche di Webpack. Gestito da Ivan Akulov.
    • Miglioramenti delle prestazioni di React in Notion, una guida di Ivan Akulov su come migliorare le prestazioni in React, con molti suggerimenti utili per rendere l'app più veloce di circa il 30%.
    • React Refresh Webpack Plugin (sperimentale) consente il ricaricamento a caldo che preserva lo stato dei componenti e supporta hook e componenti di funzioni.
    • Fai attenzione ai componenti del server React a dimensione zero, un nuovo tipo di componenti proposto che non avrà alcun impatto sulle dimensioni del pacchetto. Il progetto è attualmente in fase di sviluppo, ma qualsiasi feedback da parte della community è molto apprezzato (ottimo spiegatore di Sophie Alpert).
  3. Stai usando il prelettura predittiva per i blocchi JavaScript?
    Potremmo usare l'euristica per decidere quando precaricare i blocchi JavaScript. Guess.js è un insieme di strumenti e librerie che utilizzano i dati di Google Analytics per determinare quale pagina è più probabile che un utente visiterà successivamente da una determinata pagina. Sulla base dei modelli di navigazione dell'utente raccolti da Google Analytics o da altre fonti, Guess.js crea un modello di apprendimento automatico per prevedere e precaricare JavaScript che sarà richiesto in ogni pagina successiva.

    Quindi, ogni elemento interattivo riceve un punteggio di probabilità per il coinvolgimento e, sulla base di tale punteggio, uno script lato client decide di precaricare una risorsa in anticipo. Puoi integrare la tecnica nella tua applicazione Next.js, Angular e React, e c'è un plug-in Webpack che automatizza anche il processo di installazione.

    Ovviamente, potresti chiedere al browser di consumare dati non necessari e precaricare le pagine indesiderate, quindi è una buona idea essere piuttosto prudenti nel numero di richieste precaricate. Un buon caso d'uso potrebbe essere il precaricamento degli script di convalida richiesti durante il checkout o il precaricamento speculativo quando un invito all'azione critico entra nel viewport.

    Hai bisogno di qualcosa di meno sofisticato? DNStradamus esegue il precaricamento DNS per i collegamenti in uscita così come appaiono nel viewport. Quicklink, InstantClick e Instant.page sono piccole librerie che precaricano automaticamente i collegamenti nel viewport durante il tempo di inattività nel tentativo di caricare più velocemente le navigazioni della pagina successiva. Quicklink permette di precaricare i percorsi di React Router e Javascript; inoltre è attento ai dati, quindi non esegue il precaricamento su 2G o se Data-Saver è attivo. Lo stesso vale per Instant.page se la modalità è impostata per utilizzare il prelettura del viewport (che è un'impostazione predefinita).

    Se vuoi approfondire la scienza del prefetch predittivo in dettaglio, Divya Tagtachian ha un ottimo discorso su The Art of Predictive Prefetch, coprendo tutte le opzioni dall'inizio alla fine.

  4. Approfitta delle ottimizzazioni per il tuo motore JavaScript di destinazione.
    Studia quali motori JavaScript dominano nella tua base di utenti, quindi esplora i modi per ottimizzarli. Ad esempio, durante l'ottimizzazione per V8 che viene utilizzato in Blink-browser, runtime Node.js ed Electron, utilizzare lo streaming di script per gli script monolitici.

    Lo streaming di script consente l'analisi degli script async o defer scripts su un thread in background separato una volta avviato il download, migliorando così in alcuni casi i tempi di caricamento della pagina fino al 10%. In pratica, usa <script defer> nel <head> , in modo che i browser possano scoprire la risorsa in anticipo e quindi analizzarla sul thread in background.

    Avvertenza : Opera Mini non supporta il differimento dello script, quindi se stai sviluppando per l'India o l'Africa, il differimento defer ignorato, con conseguente blocco del rendering fino a quando lo script non è stato valutato (grazie Jeremy!) .

    Puoi anche collegarti alla cache del codice di V8, suddividendo le librerie dal codice che le utilizza, o viceversa, unire le librerie e i loro usi in un unico script, raggruppare piccoli file ed evitare script inline. O forse anche usare v8-compile-cache.

    Quando si tratta di JavaScript in generale, ci sono anche alcune pratiche che vale la pena tenere a mente:

    • Concetti di codice pulito per JavaScript, un'ampia raccolta di modelli per la scrittura di codice leggibile, riutilizzabile e refactorable.
    • Puoi comprimere i dati da JavaScript con l'API CompressionStream, ad esempio in gzip prima di caricare i dati (Chrome 80+).
    • Perdite di memoria della finestra staccata e Correzione delle perdite di memoria nelle app Web sono guide dettagliate su come trovare e correggere le perdite di memoria JavaScript complicate. Inoltre, puoi utilizzare queryObjects(SomeConstructor) dalla console DevTools ( grazie, Mathias! ).
    • Le riesportazioni sono dannose per il caricamento e le prestazioni di runtime ed evitarle può aiutare a ridurre significativamente le dimensioni del pacchetto.
    • Possiamo migliorare le prestazioni di scorrimento con listener di eventi passivi impostando un flag nel parametro options . Quindi i browser possono scorrere la pagina immediatamente, anziché dopo che l'ascoltatore ha terminato. (tramite Kayce baschi).
    • Se hai ascoltatori scroll o touch* , passa passive: true a addEventListener. Questo dice al browser che non hai intenzione di chiamare event.preventDefault() all'interno, quindi può ottimizzare il modo in cui gestisce questi eventi. (via Ivan Akulov)
    • Possiamo ottenere una migliore pianificazione JavaScript con isInputPending(), una nuova API che tenta di colmare il divario tra caricamento e reattività con i concetti di interrupt per gli input degli utenti sul Web e consente a JavaScript di essere in grado di verificare l'input senza cedere a il browser.
    • Puoi anche rimuovere automaticamente un listener di eventi dopo che è stato eseguito.
    • Warp di Firefox recentemente rilasciato, un aggiornamento significativo di SpiderMonkey (spedito in Firefox 83), Baseline Interpreter e sono disponibili anche alcune strategie di ottimizzazione JIT.
Un'illustrazione per aiutarti a comprendere il caricamento del tempo e la reattività
Un banner blu che mostra JS in esecuzione con linee bianche in spazi regolari che rappresentano il momento in cui controlliamo in modo proattivo se c'è l'input dell'utente senza incorrere nell'overhead di cedere l'esecuzione al browser e viceversa
isInputPending() è una nuova API del browser che tenta di colmare il divario tra caricamento e reattività. (Anteprima grande)
Un'illustrazione di una mappa che mostra la catena di ogni richiesta a domini diversi, fino agli script di ottave parti
La mappa delle richieste per CNN.com che mostra la catena di ogni richiesta a domini diversi, fino agli script di ottave parti. Fonte. (Grande anteprima)
  1. Preferisci sempre ospitare autonomamente risorse di terze parti.
    Ancora una volta, ospita automaticamente le tue risorse statiche per impostazione predefinita. È comune presumere che se molti siti utilizzano la stessa CDN pubblica e la stessa versione di una libreria JavaScript o di un font web, i visitatori atterrerebbero sul nostro sito con gli script e i font già memorizzati nella cache del browser, velocizzando notevolmente la loro esperienza . Tuttavia, è molto improbabile che accada.

    Per motivi di sicurezza, per evitare il fingerprinting, i browser hanno implementato la memorizzazione nella cache partizionata che è stata introdotta in Safari nel 2013 e in Chrome l'anno scorso. Quindi, se due siti puntano allo stesso identico URL di risorse di terze parti, il codice viene scaricato una volta per dominio e la cache viene "sandbox" in quel dominio a causa delle implicazioni sulla privacy ( grazie, David Calhoun! ). Pertanto, l'utilizzo di una CDN pubblica non porterà automaticamente a prestazioni migliori.

    Inoltre, vale la pena notare che le risorse non risiedono nella cache del browser per tutto il tempo previsto e le risorse di prima parte hanno maggiori probabilità di rimanere nella cache rispetto alle risorse di terze parti. Pertanto, l'hosting automatico è generalmente più affidabile e sicuro e anche migliore per le prestazioni.

  2. Limita l'impatto degli script di terze parti.
    Con tutte le ottimizzazioni delle prestazioni in atto, spesso non possiamo controllare gli script di terze parti provenienti da requisiti aziendali. Le metriche degli script di terze parti non sono influenzate dall'esperienza dell'utente finale, quindi troppo spesso un singolo script finisce per chiamare una lunga coda di odiosi script di terze parti, rovinando così uno sforzo prestazionale dedicato. Per contenere e mitigare le penalità prestazionali che questi script comportano, non è sufficiente rinviarne il caricamento e l'esecuzione e riscaldare le connessioni tramite suggerimenti sulle risorse, ad esempio dns-prefetch o preconnect .

    Attualmente il 57% di tutto il tempo di esecuzione del codice JavaScript viene speso su codice di terze parti. Il sito mobile mediano accede a 12 domini di terze parti , con una mediana di 37 richieste diverse (o circa 3 richieste rivolte a ciascuna terza parte).

    Inoltre, queste terze parti spesso invitano script di quarte parti a partecipare, finendo con un enorme collo di bottiglia nelle prestazioni, a volte arrivando agli script di ottave parti su una pagina. Quindi controllare regolarmente le dipendenze e i gestori di tag può portare con sé sorprese costose.

    Un altro problema, come ha spiegato Yoav Weiss nel suo intervento sugli script di terze parti, è che in molti casi questi script scaricano risorse dinamiche. Le risorse cambiano tra i caricamenti della pagina, quindi non sappiamo necessariamente da quali host verranno scaricate le risorse e quali sarebbero.

    Il rinvio, come mostrato sopra, potrebbe essere solo l'inizio, poiché gli script di terze parti rubano anche larghezza di banda e tempo di CPU dalla tua app. Potremmo essere un po' più aggressivi e caricarli solo quando la nostra app è stata inizializzata.

    /* Before */ const App = () => { return <div> <script> window.dataLayer = window.dataLayer || []; function gtag(){...} gtg('js', new Date()); </script> </div> } /* After */ const App = () => { const[isRendered, setRendered] = useState(false); useEffect(() => setRendered(true)); return <div> {isRendered ? <script> window.dataLayer = window.dataLayer || []; function gtag(){...} gtg('js', new Date()); </script> : null} </div> }

    In un fantastico post su "Ridurre l'impatto sulla velocità del sito dei tag di terze parti", Andy Davies esplora una strategia per ridurre al minimo l'impronta di terze parti, dall'identificazione dei loro costi alla riduzione del loro impatto.

    Secondo Andy, ci sono due modi in cui i tag influiscono sulla velocità del sito: competono per la larghezza di banda della rete e il tempo di elaborazione sui dispositivi dei visitatori e, a seconda di come vengono implementati, possono ritardare anche l'analisi HTML. Quindi il primo passo è identificare l'impatto che le terze parti hanno, testando il sito con e senza script utilizzando WebPageTest. Con la Request Map di Simon Hearne, possiamo anche visualizzare terze parti su una pagina insieme ai dettagli sulla loro dimensione, tipo e cosa ha attivato il loro caricamento.

    Preferibilmente auto-host e utilizzare un unico nome host, ma anche utilizzare una mappa delle richieste per esporre le chiamate di quarte parti e rilevare quando gli script cambiano. Puoi utilizzare l'approccio di Harry Roberts per l'auditing di terze parti e produrre fogli di calcolo come questo (controlla anche il flusso di lavoro di auditing di Harry).

    Successivamente, possiamo esplorare alternative leggere agli script esistenti e sostituire lentamente i duplicati e i principali colpevoli con opzioni più leggere. Forse alcuni degli script potrebbero essere sostituiti con il loro pixel di tracciamento di fallback invece del tag completo.

    Esempio a sinistra che mostra 3 KB di JavaScript utilizzando l'elemento personalizzato lite-youtube, esempio centrale e destro che mostra +540 KB di JavaScript con l'elemento personalizzato lite-youtube
    Caricamento di YouTube con facciate, ad esempio lite-youtube-embed che è significativamente più piccolo di un vero player di YouTube. (Fonte immagine) (Anteprima grande)

    Se non è fattibile, possiamo almeno caricare in modo pigro risorse di terze parti con le facciate, ovvero un elemento statico che sembra simile all'effettiva terza parte incorporata, ma non è funzionale e quindi molto meno gravoso sul caricamento della pagina. Il trucco, quindi, è caricare l'effettivo incorporamento solo sull'interazione .

    Ad esempio, possiamo utilizzare:

    • lite-vimeo-embed per il lettore Vimeo,
    • lite-vimeo per il lettore Vimeo,
    • lite-youtube-embed per il player di YouTube,
    • react-live-chat-loader per una chat dal vivo (caso di studio e un altro caso di studio),
    • lazyframe per iframe.

    Uno dei motivi per cui i tag manager sono generalmente di grandi dimensioni è a causa dei numerosi esperimenti simultanei che vengono eseguiti contemporaneamente, insieme a molti segmenti di utenti, URL di pagine, siti ecc., quindi, secondo Andy, ridurli può ridurre entrambi la dimensione del download e il tempo necessario per eseguire lo script nel browser.

    E poi ci sono frammenti anti-sfarfallio. Terze parti come Google Optimize, Visual Web Optimizer (VWO) e altri sono unanimi nell'utilizzarli. Questi frammenti vengono solitamente iniettati insieme all'esecuzione di test A/B : per evitare lo sfarfallio tra i diversi scenari di test, nascondono il body del documento con opacity: 0 , quindi aggiunge una funzione che viene chiamata dopo alcuni secondi per ripristinare l' opacity . Ciò si traduce spesso in enormi ritardi nel rendering a causa degli ingenti costi di esecuzione lato client.

    Sette anteprime mostrate da 0,0 secondi a 6,0 secondi che mostrano come e quando i contenuti vengono nascosti dallo snippet anti-sfarfallio quando un visitatore avvia la navigazione
    Con i test A/B in uso, i clienti vedevano spesso uno sfarfallio come questo. Gli snippet anti-sfarfallio lo impediscono, ma costano anche in termini di prestazioni. Via Andy Davis. (Grande anteprima)

    Tieni quindi traccia della frequenza con cui viene attivato il timeout anti-sfarfallio e riduci il timeout. L'impostazione predefinita blocca la visualizzazione della tua pagina fino a 4 secondi, il che rovinerà i tassi di conversione. Secondo Tim Kadlec, "Gli amici non lasciano che gli amici facciano test A/B lato client". Il test A/B lato server su CDN (ad es. Edge Computing o Edge Slice Rerendering) è sempre un'opzione più efficiente.

    Se hai a che fare con l'onnipotente Google Tag Manager , Barry Pollard fornisce alcune linee guida per contenere l'impatto di Google Tag Manager. Inoltre, Christian Schaefer esplora le strategie per caricare gli annunci.

    Attenzione: alcuni widget di terze parti si nascondono dagli strumenti di controllo, quindi potrebbero essere più difficili da individuare e misurare. Per sottoporre a stress test di terze parti, esamina i riepiloghi bottom-up nella pagina del profilo delle prestazioni in DevTools, verifica cosa succede se una richiesta è bloccata o è scaduta: per quest'ultimo, puoi utilizzare il server Blackhole di WebPageTest blackhole.webpagetest.org che hai può puntare a domini specifici nel file hosts .

    Quali opzioni abbiamo allora? Prendi in considerazione l'utilizzo di service worker eseguendo il download della risorsa con un timeout e se la risorsa non ha risposto entro un determinato timeout, restituisci una risposta vuota per indicare al browser di continuare con l'analisi della pagina. Puoi anche registrare o bloccare le richieste di terze parti che non vanno a buon fine o che non soddisfano determinati criteri. Se puoi, carica lo script di terze parti dal tuo server anziché dal server del fornitore e caricalo in modo lento.

    Un'altra opzione è stabilire una politica di sicurezza dei contenuti (CSP) per limitare l'impatto di script di terze parti, ad esempio vietando il download di audio o video. L'opzione migliore è incorporare gli script tramite <iframe> in modo che gli script siano in esecuzione nel contesto dell'iframe e quindi non abbiano accesso al DOM della pagina e non possano eseguire codice arbitrario sul tuo dominio. Gli iframe possono essere ulteriormente vincolati utilizzando l'attributo sandbox , quindi puoi disabilitare qualsiasi funzionalità che iframe potrebbe fare, ad esempio impedire l'esecuzione di script, impedire avvisi, invio di moduli, plug-in, accesso alla navigazione in alto e così via.

    Potresti anche tenere sotto controllo le terze parti tramite l'intasamento delle prestazioni nel browser con le politiche delle funzionalità, una funzionalità relativamente nuova che ti consente attivare o disattivare alcune funzionalità del browser sul tuo sito. (Come nota a margine, potrebbe anche essere utilizzato per evitare immagini sovradimensionate e non ottimizzate, supporti non dimensionati, script di sincronizzazione e altro). Attualmente supportato nei browser basati su Blink.

    /* Via Tim Kadlec. https://timkadlec.com/remembers/2020-02-20-in-browser-performance-linting-with-feature-policies/ */ /* Block the use of the Geolocation API with a Feature-Policy header. */ Feature-Policy: geolocation 'none'
    /* Via Tim Kadlec. https://timkadlec.com/remembers/2020-02-20-in-browser-performance-linting-with-feature-policies/ */ /* Block the use of the Geolocation API with a Feature-Policy header. */ Feature-Policy: geolocation 'none'

    Poiché molti script di terze parti sono in esecuzione negli iframe, probabilmente è necessario essere scrupolosi nel limitare le loro autorizzazioni. Gli iframe in modalità sandbox sono sempre una buona idea e ciascuna delle limitazioni può essere revocata tramite una serie di valori di allow nell'attributo sandbox . Il sandboxing è supportato quasi ovunque, quindi limita gli script di terze parti al minimo indispensabile di ciò che dovrebbero essere autorizzati a fare.

    Uno screenshot del sito Web ThirdPartyWeb.Today che mostra quanto tempo impiegano in media gli script dell'entità per essere eseguiti
    ThirdPartyWeb.Today raggruppa tutti gli script di terze parti per categoria (analytics, social, advertising, hosting, tag manager ecc.) e visualizza quanto tempo impiegano gli script dell'entità per essere eseguiti (in media). (Grande anteprima)

    Prendi in considerazione l'utilizzo di un osservatore di intersezione; ciò consentirebbe agli annunci di essere iframe mentre si inviano ancora eventi o si ottengono le informazioni di cui hanno bisogno dal DOM (ad es. visibilità dell'annuncio). Fai attenzione alle nuove politiche come la politica delle funzionalità, i limiti delle dimensioni delle risorse e la priorità CPU/larghezza di banda per limitare le funzionalità Web dannose e gli script che rallenteranno il browser, ad esempio script sincroni, richieste XHR sincrone, document.write e implementazioni obsolete.

    Infine, quando scegli un servizio di terze parti, valuta la possibilità di controllare ThirdPartyWeb.Today di Patrick Hulce, un servizio che raggruppa tutti gli script di terze parti per categoria (analisi, social, pubblicità, hosting, tag manager ecc.) e visualizza per quanto tempo gli script dell'entità prendere per eseguire (in media). Ovviamente, le entità più grandi hanno il peggior impatto sulle prestazioni delle pagine in cui si trovano. Semplicemente scorrendo la pagina, avrai un'idea dell'impronta delle prestazioni che dovresti aspettarti.

    Ah, e non dimentichiamoci dei soliti sospetti: al posto dei widget di terze parti per la condivisione, possiamo utilizzare pulsanti di condivisione social statici (tipo SSBG) e link statici a mappe interattive al posto delle mappe interattive.

Un esempio grafico che confronta la percentuale di richieste di prima e terza parte: 399 KB pari al 27% delle richieste di prima parte e 1,15 MB pari al 73% delle richieste di terze parti
Casper.com ha pubblicato un case study dettagliato su come sono riusciti a radere 1,7 secondi dal sito ospitando autonomamente Optimizely. Potrebbe valerne la pena. (Fonte immagine) (Anteprima grande)
  1. Imposta correttamente le intestazioni della cache HTTP.
    La memorizzazione nella cache sembra essere una cosa così ovvia da fare, ma potrebbe essere piuttosto difficile da correggere. È necessario ricontrollare che le intestazioni di expires , max-age , cache-control e altre cache HTTP siano state impostate correttamente. Senza le intestazioni della cache HTTP corrette, i browser le imposteranno automaticamente al 10% del tempo trascorso last-modified , finendo con una potenziale cache insufficiente e eccessiva.

    In generale, le risorse dovrebbero essere memorizzabili nella cache per un tempo molto breve (se è probabile che cambino) o indefinitamente (se sono statiche): puoi semplicemente modificare la loro versione nell'URL quando necessario. Puoi chiamarla strategia Cache-Forever, in cui potremmo inoltrare le intestazioni Cache-Control e Expires al browser per consentire alle risorse di scadere solo in un anno. Quindi, il browser non farebbe nemmeno una richiesta per l'asset se lo ha nella cache.

    L'eccezione sono le risposte API (ad es /api/user ). Per impedire la memorizzazione nella cache, possiamo utilizzare private, no store e non max-age=0, no-store :

     Cache-Control: private, no-store

    Usa Cache-control: immutable per evitare la riconvalida di lunghe durate della cache esplicita quando gli utenti premono il pulsante di ricarica. Per il caso di ricarica, immutable salva le richieste HTTP e migliora il tempo di caricamento dell'HTML dinamico poiché non competono più con la moltitudine di 304 risposte.

    Un tipico esempio in cui vogliamo usare immutable sono le risorse CSS/JavaScript con un hash nel loro nome. Per loro, probabilmente vogliamo memorizzare nella cache il più a lungo possibile e assicurarci che non vengano mai riconvalidati:

    Cache-Control: max-age: 31556952, immutable

    Secondo la ricerca di Colin Bendell, immutable riduce 304 reindirizzamenti di circa il 50% poiché anche con max-age in uso, i client continuano a riconvalidare e bloccare al momento dell'aggiornamento. È supportato in Firefox, Edge e Safari e Chrome sta ancora discutendo il problema.

    Secondo Web Almanac, "il suo utilizzo è cresciuto fino al 3,5% ed è ampiamente utilizzato nelle risposte di terze parti di Facebook e Google".

    Efficacia del controllo della cache in tutti i continenti con i dati recuperati da Android Chrome e iOS Safari
    Cache-Control: Immutable riduce i 304 secondi di circa il 50%, secondo la ricerca di Colin Bendell su Cloudinary. (Grande anteprima)

    Ricordi il buon vecchio stantio-mentre-riconvalidato? Quando specifichiamo il tempo di memorizzazione nella cache con l'intestazione della risposta Cache-Control (ad es. Cache-Control: max-age=604800 ), dopo la scadenza max-age , il browser recupererà il contenuto richiesto, rallentando il caricamento della pagina. Questo rallentamento può essere evitato con stale-while-revalidate ; fondamentalmente definisce una finestra di tempo aggiuntiva durante la quale una cache può utilizzare una risorsa non aggiornata purché la riconvalidi in modo asincrono in background. Pertanto, "nasconde" la latenza (sia nella rete che sul server) dai client.

    Nel giugno-luglio 2019, Chrome e Firefox hanno lanciato il supporto di stale-while-revalidate nell'intestazione HTTP Cache-Control, quindi, di conseguenza, dovrebbe migliorare le successive latenze di caricamento della pagina poiché le risorse obsolete non si trovano più nel percorso critico. Risultato: zero RTT per le visualizzazioni ripetute.

    Fai attenzione all'intestazione vary, specialmente in relazione alle CDN, e fai attenzione alle varianti di rappresentazione HTTP che aiutano a evitare un round trip aggiuntivo per la convalida ogni volta che una nuova richiesta differisce leggermente (ma non in modo significativo) dalle richieste precedenti ( grazie, Guy e Mark ! ).

    Inoltre, ricontrolla di non inviare intestazioni non necessarie (ad es. x-powered-by , pragma , x-ua-compatible , expires , X-XSS-Protection e altri) e di includere utili intestazioni di sicurezza e prestazioni (come come Content-Security-Policy , X-Content-Type-Options e altri). Infine, tieni presente il costo delle prestazioni delle richieste CORS nelle applicazioni a pagina singola.

    Nota : spesso si presume che le risorse memorizzate nella cache vengano recuperate istantaneamente, ma la ricerca mostra che il recupero di un oggetto dalla cache può richiedere centinaia di millisecondi. In effetti, secondo Simon Hearne, "a volte la rete potrebbe essere più veloce della cache e il recupero delle risorse dalla cache può essere costoso con un gran numero di risorse memorizzate nella cache (non la dimensione del file) e i dispositivi dell'utente. Ad esempio: recupero della cache media di Chrome OS raddoppia da ~50ms con 5 risorse nella cache fino a ~100ms con 25 risorse".

    Inoltre, spesso assumiamo che la dimensione del pacchetto non sia un grosso problema e gli utenti lo scaricheranno una volta e quindi utilizzeranno la versione memorizzata nella cache. Allo stesso tempo, con CI/CD inseriamo il codice in produzione più volte al giorno, la cache viene invalidata ogni volta, quindi essere strategici riguardo alla memorizzazione nella cache è importante.

    Quando si tratta di memorizzazione nella cache, ci sono molte risorse che vale la pena leggere:

    • Cache-Control for Civilians, un tuffo nella cache con Harry Roberts.
    • Il manuale di Heroku sulle intestazioni di memorizzazione nella cache HTTP,
    • Best practice per la memorizzazione nella cache di Jake Archibald,
    • Primer per la memorizzazione nella cache HTTP di Ilya Grigorik,
    • Mantenere le cose fresche con stantio-mentre-revalidate di Jeff Posnick.
    • CS Visualized: CORS di Lydia Hallie è un ottimo esplicativo su CORS, su come funziona e su come dargli un senso.
    • Parlando di CORS, ecco un piccolo aggiornamento sulla politica della stessa origine di Eric Portis.
Un grafico che mostra il tempo di recupero della cache in base al conteggio delle risorse memorizzate nella cache con diversi sistemi operativi e browser denominati a destra (dall'alto verso il basso): sistema operativo Chrome desktop, sistema operativo Android tablet, sistema operativo Android mobile, Mac desktop =S X, Windows desktop, Linux desktop
Partiamo dal presupposto che le cache del browser siano quasi istantanee, ma i dati mostrano che il recupero di un oggetto dalla cache può richiedere centinaia di millisecondi! Dalla ricerca di Simon Hearne su When Network Is Faster Than Cache. (Grande anteprima)

Ottimizzazioni di consegna

  1. Usiamo il defer per caricare JavaScript critico in modo asincrono?
    Quando l'utente richiede una pagina, il browser recupera l'HTML e costruisce il DOM, quindi recupera il CSS e costruisce il CSSOM, quindi genera un albero di rendering abbinando il DOM e il CSSOM. Se è necessario risolvere qualsiasi JavaScript, il browser non avvierà il rendering della pagina fino a quando non verrà risolto, ritardando così il rendering. Come sviluppatori, dobbiamo dire esplicitamente al browser di non aspettare e di iniziare a eseguire il rendering della pagina. Il modo per farlo per gli script è con gli attributi defer e async in HTML.

    In pratica, risulta che è meglio usare defer invece di async . Ah, qual è la differenza di nuovo? Secondo Steve Souders, una volta che gli script async arrivano, vengono eseguiti immediatamente, non appena lo script è pronto. Se ciò accade molto velocemente, ad esempio quando lo script è già nella cache, può effettivamente bloccare il parser HTML. Con defer , il browser non esegue gli script finché l'HTML non viene analizzato. Quindi, a meno che tu non abbia bisogno di JavaScript da eseguire prima di avviare il rendering, è meglio usare defer . Inoltre, più file asincroni verranno eseguiti in un ordine non deterministico.

    Vale la pena notare che ci sono alcune idee sbagliate su async e defer . Ancora più importante, async non significa che il codice verrà eseguito ogni volta che lo script è pronto; significa che verrà eseguito ogni volta che gli script sono pronti e tutto il lavoro di sincronizzazione precedente è terminato. Nelle parole di Harry Roberts, "Se inserisci uno script async dopo gli script di sincronizzazione, il tuo script async è veloce quanto lo script di sincronizzazione più lento".

    Inoltre, non è consigliabile utilizzare sia async che defer . I browser moderni supportano entrambi, ma ogni volta che vengono utilizzati entrambi gli attributi, l' async vincerà sempre.

    Se desideri approfondire i dettagli, Milica Mihajlija ha scritto una guida molto dettagliata su Costruire il DOM più velocemente, entrando nei dettagli dell'analisi speculativa, dell'asincrono e del differimento.

  2. Carica pigramente componenti costosi con IntersectionObserver e suggerimenti per la priorità.
    In generale, si consiglia di caricare in modo pigro tutti i componenti costosi, come JavaScript pesante, video, iframe, widget e potenzialmente immagini. Il caricamento lento nativo è già disponibile per immagini e iframe con l'attributo di loading (solo Chromium). Sotto il cofano, questo attributo rinvia il caricamento della risorsa fino a quando non raggiunge una distanza calcolata dal viewport.
    <!-- Lazy loading for images, iframes, scripts. Probably for images outside of the viewport. --> <img loading="lazy" ... /> <iframe loading="lazy" ... /> <!-- Prompt an early download of an asset. For critical images, eg hero images. --> <img loading="eager" ... /> <iframe loading="eager" ... />

    Tale soglia dipende da alcune cose, dal tipo di risorsa immagine che viene recuperata al tipo di connessione efficace. Ma gli esperimenti condotti utilizzando Chrome su Android suggeriscono che su 4G, il 97,5% delle immagini under-the-fold caricate in modo pigro sono state completamente caricate entro 10 ms da quando sono diventate visibili, quindi dovrebbe essere sicuro.

    Possiamo anche utilizzare l'attributo di importance ( high o low ) su un elemento <script> , <img> o <link> (solo Blink). In effetti, è un ottimo modo per ridurre la priorità alle immagini nei caroselli, nonché per ridefinire la priorità degli script. Tuttavia, a volte potremmo aver bisogno di un controllo un po' più granulare.

    <!-- When the browser assigns "High" priority to an image, but we don't actually want that. --> <img src="less-important-image.svg" importance="low" ... /> <!-- We want to initiate an early fetch for a resource, but also deprioritize it. --> <link rel="preload" importance="low" href="/script.js" as="script" />

    Il modo più efficace per eseguire un caricamento lento leggermente più sofisticato consiste nell'usare l'API Intersection Observer che fornisce un modo per osservare in modo asincrono le modifiche nell'intersezione di un elemento di destinazione con un elemento predecessore o con il viewport di un documento di primo livello. Fondamentalmente, devi creare un nuovo oggetto IntersectionObserver , che riceve una funzione di callback e un insieme di opzioni. Quindi aggiungiamo un obiettivo da osservare.

    La funzione di callback viene eseguita quando il target diventa visibile o invisibile, quindi quando intercetta il viewport, puoi iniziare a intraprendere alcune azioni prima che l'elemento diventi visibile. In effetti, abbiamo un controllo granulare su quando deve essere invocata la richiamata dell'osservatore, con rootMargin (margine attorno alla radice) e threshold (un singolo numero o una matrice di numeri che indicano a quale percentuale della visibilità del bersaglio stiamo puntando).

    Alejandro Garcia Anglada ha pubblicato un pratico tutorial su come implementarlo effettivamente, Rahul Nanwani ha scritto un post dettagliato sul caricamento lento delle immagini in primo piano e di sfondo e Google Fundamentals fornisce anche un tutorial dettagliato sul caricamento lento di immagini e video con Intersection Observer.

    Ricordi lunghe letture di narrazione artistica con oggetti in movimento e appiccicosi? Puoi anche implementare lo scrollytelling performante con Intersection Observer.

    Controlla di nuovo cos'altro potresti caricare pigro. Anche le stringhe di traduzione e le emoji a caricamento lento potrebbero aiutare. In questo modo, Mobile Twitter è riuscito a ottenere un'esecuzione JavaScript più veloce dell'80% dalla nuova pipeline di internazionalizzazione.

    Una breve parola di cautela però: vale la pena notare che il caricamento lento dovrebbe essere un'eccezione piuttosto che la regola. Probabilmente non è ragionevole caricare in modo pigro tutto ciò che si desidera che le persone vedano rapidamente, ad esempio immagini della pagina del prodotto, immagini dell'eroe o uno script necessario affinché la navigazione principale diventi interattiva.

Un esempio che mostra una vecchia soglia di 3000 px con 160 KB di download (a sinistra) mentre la nuova soglia ha una quantità di 1250 px con solo 90 KB di download (a destra) che mostra un miglioramento del risparmio di dati pigri nel caricamento di img
Sulle connessioni veloci (es. 4G), le soglie di distanza dalla finestra di visualizzazione di Chrome sono state recentemente ridotte da 3000px a 1250px, e sulle connessioni più lente (es. 3G), la soglia è cambiata da 4000px a 2500px. (Grande anteprima)
Un'illustrazione con testo attorno a un telefono cellulare con l'interfaccia utente di Twitter mostrata, che spiega i miglioramenti degli strumenti da stringhe di traduzione a carico lento
Con il caricamento lento delle stringhe di traduzione, Mobile Twitter è riuscito a ottenere un'esecuzione JavaScript più veloce dell'80% dalla nuova pipeline di internazionalizzazione. (Credito immagine: Addy Osmani) (Anteprima grande)
  1. Carica le immagini progressivamente.
    Potresti persino portare il caricamento lento al livello successivo aggiungendo il caricamento progressivo delle immagini alle tue pagine. Analogamente a Facebook, Pinterest, Medium e Wolt, è possibile caricare prima immagini di bassa qualità o addirittura sfocate, quindi, mentre la pagina continua a caricarsi, sostituirle con le versioni di qualità completa utilizzando la tecnica BlurHash o LQIP (Low Quality Image Placeholders) tecnica.

    Le opinioni divergono se queste tecniche migliorano o meno l'esperienza dell'utente, ma migliorano decisamente il tempo di First Contentful Paint. Possiamo persino automatizzarlo utilizzando SQIP che crea una versione di bassa qualità di un'immagine come segnaposto SVG o segnaposto immagine sfumata con gradienti lineari CSS.

    Questi segnaposto potrebbero essere incorporati all'interno di HTML poiché si comprimono naturalmente bene con i metodi di compressione del testo. Nel suo articolo, Dean Hume ha descritto come questa tecnica può essere implementata utilizzando Intersection Observer.

    Ricaderci? Se il browser non supporta l'osservatore di intersezione, possiamo comunque caricare in modo lento un polyfill o caricare immediatamente le immagini. E c'è anche una libreria per questo.

    Vuoi diventare più elegante? È possibile tracciare le immagini e utilizzare forme e bordi primitivi per creare un segnaposto SVG leggero, caricarlo prima e quindi passare dall'immagine vettoriale segnaposto all'immagine bitmap (caricata).

  2. Tre diverse versioni che mostrano la tecnica di caricamento pigro SVG di Jose M. Perez, una versione simile all'arte del cubismo a sinistra, una versione sfocata pixelata al centro e un'immagine corretta dello stesso Jose a destra
    Tecnica di caricamento pigro SVG di Jose M. Perez. (Grande anteprima)
  3. Rimandi il rendering con content-visibility ?
    Per layout complessi con molti blocchi di contenuto, immagini e video, la decodifica dei dati e il rendering dei pixel potrebbero essere un'operazione piuttosto costosa, specialmente su dispositivi di fascia bassa. Con content-visibility: auto , possiamo richiedere al browser di saltare il layout dei bambini mentre il contenitore è al di fuori del viewport.

    Ad esempio, potresti saltare il rendering del piè di pagina e delle sezioni finali sul caricamento iniziale:

    footer { content-visibility: auto; contain-intrinsic-size: 1000px; /* 1000px is an estimated height for sections that are not rendered yet. */ }

    Si noti che la visibilità del contenuto: auto; si comporta come overflow: nascosto; , ma puoi risolverlo applicando padding-left e padding-right invece del margin-left: auto; , margin-right: auto; e una larghezza dichiarata. Il riempimento sostanzialmente consente agli elementi di traboccare nella casella del contenuto ed entrare nella casella di riempimento senza lasciare il modello della scatola nel suo insieme e essere tagliato.

    Inoltre, tieni presente che potresti introdurre alcuni CLS quando alla fine viene eseguito il rendering di nuovi contenuti, quindi è una buona idea usare contain-intrinsic-size con un segnaposto di dimensioni adeguate ( grazie, Una! ).

    Thijs Terluin ha molti più dettagli su entrambe le proprietà e su come viene calcolata la contain-intrinsic-size dal browser, Malte Ubl mostra come calcolarla e un breve video esplicativo di Jake e Surma spiega come funziona.

    E se hai bisogno di diventare un po' più granulare, con CSS Containment, puoi saltare manualmente il layout, lo stile e il lavoro di disegno per i discendenti di un nodo DOM se hai bisogno solo di dimensioni, allineamento o stili calcolati su altri elementi — o l'elemento è attualmente fuori tela.

Le prestazioni di rendering al carico iniziale sono 2.288 ms per la linea di base (a sinistra) e 13.464 ms per i blocchi con visibilità del contenuto: auto (a destra)
Nella demo, l'applicazione content-visibility: auto alle aree di contenuto in blocchi offre un aumento delle prestazioni di rendering di 7 volte al carico iniziale. (Grande anteprima)
  1. Rinvii la decodifica con decoding="async" ?
    A volte il contenuto appare fuori schermo, ma vogliamo assicurarci che sia disponibile quando i clienti ne hanno bisogno, idealmente, non bloccando nulla nel percorso critico, ma decodificando e visualizzando in modo asincrono. Possiamo usare decoding="async" per dare al browser il permesso di decodificare l'immagine fuori dal thread principale, evitando l'impatto dell'utente del tempo CPU utilizzato per decodificare l'immagine (tramite Malte Ubl):

    <img decoding="async" … />

    In alternativa, per le immagini fuori schermo, possiamo visualizzare prima un segnaposto e, quando l'immagine è all'interno del viewport, utilizzando IntersectionObserver, attivare una chiamata di rete per scaricare l'immagine in background. Inoltre, possiamo rinviare il rendering fino alla decodifica con img.decode() o scaricare l'immagine se l'API Image Decode non è disponibile.

    Durante il rendering dell'immagine, ad esempio, possiamo utilizzare animazioni di dissolvenza in entrata. Katie Hempenius e Addy Osmani condividono ulteriori approfondimenti nel loro discorso Speed ​​at Scale: Web Performance Tips and Tricks from the Trenches.

  2. Generate e servite CSS critici?
    Per garantire che i browser inizino a visualizzare la tua pagina il più rapidamente possibile, è diventata una pratica comune raccogliere tutti i CSS necessari per iniziare a eseguire il rendering della prima parte visibile della pagina (nota come "CSS critico" o "CSS above-the-fold ") e includerlo in linea nel <head> della pagina, riducendo così i roundtrip. A causa delle dimensioni limitate dei pacchetti scambiati durante la fase di avvio lento, il tuo budget per CSS critici è di circa 14 KB.

    Se vai oltre, il browser avrà bisogno di ulteriori roundtrip per recuperare più stili. CriticalCSS e Critical ti consentono di generare CSS critici per ogni modello che stai utilizzando. Nella nostra esperienza, tuttavia, nessun sistema automatico è mai stato migliore della raccolta manuale di CSS critici per ogni modello, e in effetti questo è l'approccio a cui siamo tornati di recente.

    È quindi possibile incorporare CSS critici e caricare in modo pigro il resto con il plug-in Critters Webpack. Se possibile, prendi in considerazione l'utilizzo dell'approccio inline condizionale utilizzato dal Filament Group o converti al volo il codice inline in risorse statiche.

    Se attualmente carichi il tuo CSS completo in modo asincrono con librerie come loadCSS, non è davvero necessario. Con media="print" , puoi indurre il browser a recuperare il CSS in modo asincrono ma applicandolo all'ambiente dello schermo una volta caricato. ( grazie, Scott! )

    <!-- Via Scott Jehl. https://www.filamentgroup.com/lab/load-css-simpler/ --> <!-- Load CSS asynchronously, with low priority --> <link rel="stylesheet" href="full.css" media="print" onload="this.media='all'" />

    Quando si raccolgono tutti i CSS critici per ogni modello, è comune esplorare solo l'area "above-the-fold". Tuttavia, per layout complessi, potrebbe essere una buona idea includere anche le basi del layout per evitare enormi costi di ricalcolo e ridisegno, danneggiando di conseguenza il punteggio di Core Web Vitals.

    Cosa succede se un utente ottiene un URL che si collega direttamente al centro della pagina ma il CSS non è stato ancora scaricato? In tal caso, è diventato comune nascondere i contenuti non critici, ad esempio con l' opacity: 0; in CSS integrato e opacity: 1 nel file CSS completo e visualizzalo quando CSS è disponibile. Tuttavia, ha un grosso svantaggio , poiché gli utenti con connessioni lente potrebbero non essere mai in grado di leggere il contenuto della pagina. Ecco perché è meglio mantenere sempre visibile il contenuto, anche se potrebbe non avere uno stile adeguato.

    L'inserimento di CSS critici (e altre risorse importanti) in un file separato nel dominio principale presenta vantaggi, a volte anche più dell'inlining, a causa della memorizzazione nella cache. Chrome apre in modo speculativo una seconda connessione HTTP al dominio principale quando richiede la pagina, il che elimina la necessità di una connessione TCP per recuperare questo CSS. Ciò significa che puoi creare una serie di file CSS critici (ad esempio critical-homepage.css , critical-product-page.css ecc.) e servirli dalla tua radice, senza doverli incorporare. ( grazie, Filippo! )

    Un avvertimento: con HTTP/2, i CSS critici potrebbero essere archiviati in un file CSS separato e inviati tramite un server push senza gonfiare l'HTML. Il problema è che il push del server è stato problematico con molti trucchi e condizioni di gara su tutti i browser. Non è mai stato supportato in modo coerente e ha avuto alcuni problemi di memorizzazione nella cache (vedi diapositiva 114 in poi della presentazione di Hooman Beheshti).

    L'effetto potrebbe, infatti, essere negativo e gonfiare i buffer di rete, impedendo la consegna di frame autentici nel documento. Quindi non è stato molto sorprendente che per il momento Chrome stia pianificando di rimuovere il supporto per Server Push.

  3. Prova a raggruppare le tue regole CSS.
    Ci siamo abituati ai CSS critici, ma ci sono alcune ottimizzazioni che potrebbero andare oltre. Harry Roberts ha condotto una ricerca notevole con risultati abbastanza sorprendenti. Ad esempio, potrebbe essere una buona idea dividere il file CSS principale nelle sue singole media query. In questo modo, il browser recupererà CSS critici con priorità alta e tutto il resto con priorità bassa, completamente fuori dal percorso critico.

    Inoltre, evita di posizionare <link rel="stylesheet" /> prima degli snippet async . Se gli script non dipendono dai fogli di stile, considera di posizionare gli script di blocco sopra gli stili di blocco. Se lo fanno, dividi quel JavaScript in due e caricalo su entrambi i lati del tuo CSS.

    Scott Jehl ha risolto un altro problema interessante memorizzando nella cache un file CSS integrato con un addetto ai servizi, un problema comune che è familiare se si utilizzano CSS critici. Fondamentalmente, aggiungiamo un attributo ID all'elemento style in modo che sia facile trovarlo usando JavaScript, quindi un piccolo pezzo di JavaScript trova quel CSS e usa l'API Cache per memorizzarlo in una cache del browser locale (con un tipo di contenuto di text/css ) da utilizzare nelle pagine successive. Per evitare l'inlining nelle pagine successive e fare riferimento invece alle risorse memorizzate nella cache esternamente, impostiamo un cookie alla prima visita a un sito. Ecco!

    Vale la pena notare che anche lo stile dinamico può essere costoso, ma di solito solo nei casi in cui ti affidi a centinaia di componenti composti contemporaneamente renderizzati. Quindi, se stai usando CSS-in-JS, assicurati che la tua libreria CSS-in-JS ottimizzi l'esecuzione quando il tuo CSS non ha dipendenze da temi o oggetti di scena e non componi eccessivamente i componenti con stile . Aggelos Arvanitakis condivide ulteriori approfondimenti sui costi delle prestazioni di CSS-in-JS.

  4. Trasmetti in streaming le risposte?
    Spesso dimenticati e trascurati, i flussi forniscono un'interfaccia per leggere o scrivere blocchi di dati asincroni, di cui solo un sottoinsieme potrebbe essere disponibile in memoria in un dato momento. Fondamentalmente, consentono alla pagina che ha effettuato la richiesta originale di iniziare a lavorare con la risposta non appena è disponibile il primo blocco di dati e utilizzano parser ottimizzati per lo streaming per visualizzare progressivamente il contenuto.

    Potremmo creare un flusso da più fonti. Ad esempio, invece di servire una shell dell'interfaccia utente vuota e lasciare che JavaScript la popola, puoi lasciare che l'operatore del servizio costruisca un flusso in cui la shell proviene da una cache, ma il corpo proviene dalla rete. Come ha notato Jeff Posnick, se la tua app Web è alimentata da un CMS che esegue il rendering del server HTML unendo insieme modelli parziali, quel modello si traduce direttamente nell'utilizzo di risposte in streaming, con la logica del modello replicata nel lavoratore del servizio anziché nel tuo server. L'articolo The Year of Web Streams di Jake Archibald evidenzia come esattamente potresti costruirlo. L'aumento delle prestazioni è abbastanza evidente.

    Un importante vantaggio dello streaming dell'intera risposta HTML è che l'HTML visualizzato durante la richiesta di navigazione iniziale può sfruttare appieno il parser HTML in streaming del browser. I blocchi di HTML inseriti in un documento dopo il caricamento della pagina (come è comune con i contenuti popolati tramite JavaScript) non possono trarre vantaggio da questa ottimizzazione.

    Supporto del browser? Ci si arriva ancora con il supporto parziale in Chrome, Firefox, Safari ed Edge che supportano l'API e Service Workers supportati in tutti i browser moderni. E se ti senti di nuovo avventuroso, puoi controllare un'implementazione sperimentale delle richieste di streaming, che ti consente di iniziare a inviare la richiesta mentre continua a generare il corpo. Disponibile in Chrome 85.

Un'immagine che riassume l'utilizzo dei dati di salvataggio su Android Chrome e gli hit o le sessioni img medi scoperti dalla ricerca Cloudinary a novembre 2019 e aprile 2020
Secondo una ricerca Cloudinary, il 18% degli utenti globali di Android Chrome ha la modalità Lite abilitata (aka Save-Data). (Grande anteprima)
  1. Considera di rendere i tuoi componenti sensibili alla connessione.
    I dati possono essere costosi e con il carico utile in aumento, dobbiamo rispettare gli utenti che scelgono di optare per il risparmio dei dati mentre accedono ai nostri siti o app. L'intestazione della richiesta di suggerimento client Save-Data ci consente di personalizzare l'applicazione e il carico utile per utenti con vincoli di costi e prestazioni.

    In effetti, è possibile riscrivere le richieste di immagini con DPI elevati in immagini DPI basse, rimuovere i caratteri Web, effetti di parallasse fantasiosi, visualizzare in anteprima le miniature e lo scorrimento infinito, disattivare la riproduzione automatica dei video, i push del server, ridurre il numero di elementi visualizzati e ridurre la qualità dell'immagine, oppure cambia anche il modo in cui fornisci il markup. Tim Vereecke ha pubblicato un articolo molto dettagliato sulle strategie di data-s(h)aver con molte opzioni per il salvataggio dei dati.

    Chi sta usando save-data , ti starai chiedendo? Il 18% degli utenti globali di Android Chrome ha la modalità Lite abilitata (con il Save-Data attivato) ed è probabile che il numero sia più alto. Secondo la ricerca di Simon Hearne, il tasso di adesione è più alto su dispositivi più economici, ma ci sono molti valori anomali. Ad esempio: gli utenti in Canada hanno un tasso di partecipazione di oltre il 34% (rispetto al 7% circa negli Stati Uniti) e gli utenti dell'ultima ammiraglia Samsung hanno un tasso di partecipazione di quasi il 18% a livello globale.

    Con la modalità Save-Data attiva, Chrome Mobile fornirà un'esperienza ottimizzata, ovvero un'esperienza Web proxy con script differiti , font-display: swap e caricamento lento forzato. È solo più sensato costruire l'esperienza da solo piuttosto che fare affidamento sul browser per effettuare queste ottimizzazioni.

    L'intestazione è attualmente supportata solo in Chromium, sulla versione Android di Chrome o tramite l'estensione Data Saver su un dispositivo desktop. Infine, puoi anche utilizzare l'API Network Information per fornire costosi moduli JavaScript, immagini e video ad alta risoluzione in base al tipo di rete. L'API Network Information e in particolare navigator.connection.effectiveType utilizzano i valori RTT , downlink , effectiveType (e pochi altri) per fornire una rappresentazione della connessione e dei dati che gli utenti possono gestire.

    In questo contesto, Max Bock parla di componenti sensibili alla connessione e Addy Osmani parla di servizio di moduli adattivi. Ad esempio, con React, potremmo scrivere un componente che esegue il rendering in modo diverso per diversi tipi di connessione. Come suggerito da Max, un componente <Media /> in un articolo di notizie potrebbe produrre:

    • Offline : un segnaposto con testo alt ,
    • 2G / modalità save-data : un'immagine a bassa risoluzione,
    • 3G su schermo non retina: un'immagine a media risoluzione,
    • 3G su schermi Retina: immagine Retina ad alta risoluzione,
    • 4G : un video HD.

    Dean Hume fornisce un'implementazione pratica di una logica simile utilizzando un operatore di servizio. Per un video, potremmo visualizzare un poster video per impostazione predefinita, quindi visualizzare l'icona "Riproduci" nonché la shell del lettore video, i metadati del video ecc. su connessioni migliori. Come ripiego per i browser non di supporto, potremmo ascoltare l'evento canplaythrough e utilizzare Promise.race() per interrompere il caricamento del codice sorgente se l'evento canplaythrough non si attiva entro 2 secondi.

    Se vuoi approfondire un po', ecco un paio di risorse per iniziare:

    • Addy Osmani mostra come implementare il servizio adattivo in React.
    • React Adaptive Loading Hooks & Utilities fornisce frammenti di codice per React,
    • Netanel Basel esplora i componenti Connection-Aware in Angular,
    • Theodore Vorilas condivide il funzionamento del servizio di componenti adattivi utilizzando l'API di informazioni di rete in Vue.
    • Umar Hansa mostra come scaricare/eseguire selettivamente JavaScript costoso.
  2. Prendi in considerazione l'idea di rendere i tuoi componenti sensibili alla memoria del dispositivo.
    Tuttavia, la connessione di rete ci offre solo una prospettiva nel contesto dell'utente. Andando oltre, puoi anche regolare dinamicamente le risorse in base alla memoria del dispositivo disponibile, con l'API Device Memory. navigator.deviceMemory restituisce quanta RAM ha il dispositivo in gigabyte, arrotondata per difetto alla potenza di due più vicina. L'API dispone anche di un'intestazione di suggerimenti client, Device-Memory , che riporta lo stesso valore.

    Bonus : Umar Hansa mostra come rinviare script costosi con importazioni dinamiche per modificare l'esperienza in base alla memoria del dispositivo, alla connettività di rete e alla concorrenza hardware.

Un'analisi che mostra come vengono assegnate priorità alle diverse risorse in Blink a partire da Chrome 46 e versioni successive
Un'analisi che mostra come vengono assegnate priorità alle diverse risorse in Blink a partire da Chrome 46 e versioni successive. (Credito immagine: Addy Osmani) (Anteprima grande)
  1. Riscalda la connessione per accelerare la consegna.
    Usa i suggerimenti per le risorse per risparmiare tempo su dns-prefetch (che esegue una ricerca DNS in background), preconnect (che chiede al browser di avviare l'handshake della connessione (DNS, TCP, TLS) in background), prefetch (che chiede al browser per richiedere una risorsa) e preload (che precarica le risorse senza eseguirle, tra le altre cose). Ben supportato nei browser moderni, con il supporto in arrivo a breve su Firefox.

    Ricordi prerender ? Il suggerimento sulla risorsa utilizzato per richiedere al browser di creare l'intera pagina in background per la navigazione successiva. I problemi di implementazione erano piuttosto problematici, da un'enorme impronta di memoria e utilizzo della larghezza di banda a più hit di analisi registrati e impressioni degli annunci.

    Non sorprende che sia stato deprecato, ma il team di Chrome lo ha riportato come meccanismo NoState Prefetch. In effetti, Chrome tratta invece il suggerimento di prerender come un NoState Prefetch, quindi possiamo usarlo ancora oggi. Come spiega Katie Hempenius in quell'articolo, "come il prerendering, NoState Prefetch recupera le risorse in anticipo ; ma a differenza del prerendering, non esegue JavaScript né esegue il rendering di alcuna parte della pagina in anticipo".

    NoState Prefetch utilizza solo ~45MiB di memoria e le sottorisorse recuperate verranno recuperate con una priorità di rete IDLE . Da Chrome 69, NoState Prefetch aggiunge l'intestazione Scopo: Prefetch a tutte le richieste per renderle distinguibili dalla normale navigazione.

    Inoltre, fai attenzione alle alternative e ai portali di prerendering, un nuovo sforzo verso il prerendering attento alla privacy, che fornirà l' preview del contenuto per una navigazione senza interruzioni.

    L'utilizzo dei suggerimenti per le risorse è probabilmente il modo più semplice per aumentare le prestazioni e funziona davvero bene. Quando usare cosa? Come ha spiegato Addy Osmani, è ragionevole precaricare risorse che sappiamo molto probabilmente saranno utilizzate nella pagina corrente e per navigazioni future attraverso più confini di navigazione, ad esempio i pacchetti Webpack necessari per le pagine che l'utente non ha ancora visitato.

    L'articolo di Addy su "Caricamento delle priorità in Chrome" mostra in che modo Chrome interpreta esattamente i suggerimenti sulle risorse, quindi una volta che hai deciso quali risorse sono fondamentali per il rendering, puoi assegnare loro una priorità elevata. Per vedere la priorità delle tue richieste, puoi abilitare una colonna "priorità" nella tabella delle richieste di rete di Chrome DevTools (oltre a Safari).

    La maggior parte delle volte in questi giorni, utilizzeremo almeno preconnect e dns-prefetch e saremo cauti nell'usare prefetch , preload e prerender . Nota che anche con preconnect e dns-prefetch , il browser ha un limite al numero di host a cui cercherà/si connetterà in parallelo, quindi è una scommessa sicura ordinarli in base alla priorità ( grazie Philip Tellis! ).

    Poiché i caratteri di solito sono risorse importanti in una pagina, a volte è una buona idea richiedere al browser di scaricare i caratteri critici con il preload . Tuttavia, ricontrolla se aiuta effettivamente le prestazioni poiché esiste un puzzle di priorità durante il precaricamento dei caratteri: poiché il preload è considerato di grande importanza, può scavalcare risorse ancora più critiche come CSS critici. ( grazie, Barry! )

    <!-- Loading two rendering-critical fonts, but not all their weights. --> <!-- crossorigin="anonymous" is required due to CORS. Without it, preloaded fonts will be ignored. https://github.com/w3c/preload/issues/32 via https://twitter.com/iamakulov/status/1275790151642423303 --> <link rel="preload" as="font" href="Elena-Regular.woff2" type="font/woff2" crossorigin="anonymous" media="only screen and (min-width: 48rem)" /> <link rel="preload" as="font" href="Mija-Bold.woff2" type="font/woff2" crossorigin="anonymous" media="only screen and (min-width: 48rem)" />
    <!-- Loading two rendering-critical fonts, but not all their weights. --> <!-- crossorigin="anonymous" is required due to CORS. Without it, preloaded fonts will be ignored. https://github.com/w3c/preload/issues/32 via https://twitter.com/iamakulov/status/1275790151642423303 --> <link rel="preload" as="font" href="Elena-Regular.woff2" type="font/woff2" crossorigin="anonymous" media="only screen and (min-width: 48rem)" /> <link rel="preload" as="font" href="Mija-Bold.woff2" type="font/woff2" crossorigin="anonymous" media="only screen and (min-width: 48rem)" />

    Poiché <link rel="preload"> accetta un attributo media , puoi scegliere di scaricare selettivamente le risorse in base alle regole di query @media , come mostrato sopra.

    Inoltre, possiamo utilizzare gli attributi imagesrcset e imagesizes per precaricare più rapidamente le immagini degli eroi scoperte in ritardo o qualsiasi immagine caricata tramite JavaScript, ad esempio le locandine dei film:

    <!-- Addy Osmani. https://addyosmani.com/blog/preload-hero-images/ --> <link rel="preload" as="image" href="poster.jpg" image image>
    <!-- Addy Osmani. https://addyosmani.com/blog/preload-hero-images/ --> <link rel="preload" as="image" href="poster.jpg" image image>

    Possiamo anche precaricare il JSON come fetch , quindi viene scoperto prima che JavaScript lo richieda:

    <!-- Addy Osmani. https://addyosmani.com/blog/preload-hero-images/ --> <link rel="preload" as="fetch" href="foo.com/api/movies.json" crossorigin>

    Potremmo anche caricare JavaScript in modo dinamico, in modo efficace per l'esecuzione pigra dello script.

    /* Adding a preload hint to the head */ var preload = document.createElement("link"); link.href = "myscript.js"; link.rel = "preload"; link.as = "script"; document.head.appendChild(link); /* Injecting a script when we want it to execute */ var script = document.createElement("script"); script.src = "myscript.js"; document.body.appendChild(script);

    Alcuni accorgimenti da tenere a mente: il preload è utile per spostare il tempo di inizio download di una risorsa più vicino alla richiesta iniziale, ma le risorse precaricate finiscono nella cache di memoria che è legata alla pagina che effettua la richiesta. il preload funziona bene con la cache HTTP: una richiesta di rete non viene mai inviata se l'elemento è già presente nella cache HTTP.

    Pertanto, è utile per le risorse scoperte in ritardo, le immagini hero caricate tramite background-image , l'integrazione di CSS (o JavaScript) critici e il precaricamento del resto del CSS (o JavaScript).

    Un esempio che utilizza la copertina del film Greyhound con Tom Hanks per mostrare che le immagini precaricate vengono caricate prima poiché non è necessario attendere JavaScript per scoprirle
    Precarica le immagini importanti in anticipo; non c'è bisogno di aspettare JavaScript per scoprirli. (Credito immagine: "Precarica più velocemente le immagini dell'eroe scoperte in ritardo" di Addy Osmani) (Anteprima grande)

    Un tag di preload può avviare un precaricamento solo dopo che il browser ha ricevuto l'HTML dal server e il parser lookahead ha trovato il tag di preload . Il precaricamento tramite l'intestazione HTTP potrebbe essere un po' più veloce poiché non dobbiamo aspettare che il browser analizzi l'HTML per avviare la richiesta (è dibattuto però).

    I primi suggerimenti aiuteranno ulteriormente, consentendo al precaricamento di attivarsi anche prima dell'invio delle intestazioni di risposta per l'HTML (sulla roadmap in Chromium, Firefox). Inoltre, i suggerimenti per le priorità ci aiuteranno a indicare le priorità di caricamento degli script.

    Attenzione : se stai usando preload , as deve essere definito o non viene caricato nulla, inoltre i caratteri precaricati senza l'attributo crossorigin verranno recuperati due volte. Se stai utilizzando prefetch , fai attenzione ai problemi di intestazione Age in Firefox.

Un grafico che mostra il primo disegno di contenuto (in base allo stato di lavoro del server) con un conteggio da 0 a 150 in un determinato periodo di tempo (in ms)
Con un addetto ai servizi, possiamo richiedere solo il minimo indispensabile di dati e quindi trasformare tali dati in un documento HTML completo per migliorare FCP. (via Phil Walton) (Grande anteprima)
  1. Usa i service worker per la memorizzazione nella cache e i fallback di rete.
    Nessuna ottimizzazione delle prestazioni su una rete può essere più veloce di una cache archiviata localmente sulla macchina di un utente (ci sono però delle eccezioni). Se il tuo sito Web è in esecuzione su HTTPS, possiamo memorizzare nella cache le risorse statiche in una cache di servizio e archiviare i fallback offline (o anche le pagine offline) e recuperarli dalla macchina dell'utente, invece di andare in rete.

    Come suggerito da Phil Walton, con gli addetti ai servizi possiamo inviare payload HTML più piccoli generando in modo programmatico le nostre risposte. Un addetto al servizio può richiedere solo il minimo indispensabile di dati di cui ha bisogno dal server (ad esempio un contenuto HTML parziale, un file Markdown, dati JSON, ecc.), e quindi può trasformare a livello di codice quei dati in un documento HTML completo. Pertanto, una volta che un utente visita un sito e l'operatore del servizio è installato, l'utente non richiederà mai più una pagina HTML completa. L'impatto sulle prestazioni può essere piuttosto impressionante.

    Supporto del browser? Gli operatori dei servizi sono ampiamente supportati e il fallback è comunque la rete. Aiuta a migliorare le prestazioni ? Eh si, lo fa. E sta migliorando, ad esempio con il recupero in background che consente caricamenti/download in background anche tramite un addetto al servizio.

    Esistono diversi casi d'uso per un lavoratore del servizio. Ad esempio, potresti implementare la funzione "Salva per offline", gestire immagini interrotte, introdurre messaggi tra le schede o fornire strategie di memorizzazione nella cache diverse in base ai tipi di richiesta. In generale, una strategia comune affidabile consiste nell'archiviazione della shell dell'app nella cache del lavoratore del servizio insieme ad alcune pagine critiche, come la pagina offline, la prima pagina e qualsiasi altra cosa che potrebbe essere importante nel tuo caso.

    Ci sono però alcuni aspetti da tenere a mente. Con un operatore di servizio in atto, dobbiamo fare attenzione alle richieste di intervallo in Safari (se stai utilizzando Workbox per un operatore di servizio, ha un modulo di richiesta di intervallo). Se ti sei mai imbattuto in DOMException: Quota exceeded. errore nella console del browser, quindi esamina l'articolo di Gerardo Quando 7 KB equivalgono a 7 MB.

    Come scrive Gerardo, "Se stai creando un'app Web progressiva e stai riscontrando un'archiviazione della cache gonfia quando il tuo addetto ai servizi memorizza nella cache le risorse statiche servite dalle CDN, assicurati che esista l'intestazione di risposta CORS corretta per le risorse multiorigine, non memorizzi nella cache le risposte opache con il tuo addetto ai servizi involontariamente, attivi le risorse immagine cross-origin in modalità CORS aggiungendo l'attributo crossorigin al tag <img> ".

    Ci sono molte ottime risorse per iniziare con gli addetti ai servizi:

    • Service Worker Mindset, che ti aiuta a capire come lavorano gli operatori di servizio dietro le quinte e le cose da capire quando ne costruiscono uno.
    • Chris Ferdinandi fornisce un'ampia serie di articoli sugli operatori del servizio, spiegando come creare applicazioni offline e coprendo una varietà di scenari, dal salvataggio offline delle pagine visualizzate di recente all'impostazione di una data di scadenza per gli elementi in una cache di un lavoratore del servizio.

    • Insidie ​​e best practice per gli operatori del servizio, con alcuni suggerimenti sull'ambito, il ritardo della registrazione di un lavoratore del servizio e la memorizzazione nella cache del lavoratore del servizio.
    • Grande serie di Ire Aderinokun su "Offline First" con Service Worker, con una strategia sul precaching della shell dell'app.
    • Service Worker: un'introduzione con suggerimenti pratici su come utilizzare Service Worker per esperienze offline avanzate, sincronizzazioni periodiche in background e notifiche push.
    • Vale sempre la pena fare riferimento al buon vecchio libro di cucina offline di Jake Archibald con una serie di ricette su come cuocere il tuo personale di servizio.
    • Workbox è un set di librerie di operatori di servizio create appositamente per la creazione di app Web progressive.
  2. Stai eseguendo server worker sulla CDN/Edge, ad esempio per test A/B?
    A questo punto, siamo abbastanza abituati a eseguire i service worker sul client, ma con le CDN che li implementano sul server, potremmo usarli per modificare le prestazioni anche al limite.

    Ad esempio, nei test A/B, quando HTML deve variare il suo contenuto per utenti diversi, potremmo utilizzare Service Workers sui server CDN per gestire la logica. Potremmo anche eseguire lo streaming della riscrittura HTML per velocizzare i siti che utilizzano Google Fonts.

Un grafico che mostra le serie temporali delle installazioni degli addetti ai servizi su desktop e dispositivi mobili con la percentuale di pagine nel tempo tra gennaio 2016 e luglio 2020
Serie temporali dell'installazione dell'operatore di servizio. Solo lo 0,87% di tutte le pagine desktop registra un addetto ai servizi, secondo Web Almanac. (Grande anteprima)
  1. Ottimizza le prestazioni di rendering.
    Ogni volta che l'applicazione è lenta, si nota subito. Quindi dobbiamo assicurarci che non ci siano ritardi durante lo scorrimento della pagina o quando un elemento è animato e che stai raggiungendo costantemente 60 fotogrammi al secondo. Se ciò non è possibile, è preferibile almeno rendere coerenti i fotogrammi al secondo rispetto a un intervallo misto compreso tra 60 e 15. Usa will-change dei CSS per informare il browser di quali elementi e proprietà cambieranno.

    Ogni volta che si verificano, eseguire il debug di ridisegni non necessari in DevTools:

    • Misura le prestazioni di rendering in runtime. Dai un'occhiata ad alcuni suggerimenti utili su come dargli un senso.
    • Per iniziare, dai un'occhiata al corso gratuito Udacity di Paul Lewis sull'ottimizzazione del rendering del browser e all'articolo di Georgy Marchuk sulla pittura del browser e considerazioni per le prestazioni web.
    • Abilita Paint Flashing in "Altri strumenti → Rendering → Paint Flashing" in Firefox DevTools.
    • In React DevTools, seleziona "Evidenzia aggiornamenti" e abilita "Registra perché ogni componente è stato renderizzato",
    • Puoi anche utilizzare Why Did You Render, quindi quando un componente viene rieseguito, un flash ti avviserà della modifica.

    Stai usando un layout in muratura? Tieni presente che potrebbe essere in grado di costruire un layout in muratura con la sola griglia CSS, molto presto.

    Se vuoi approfondire l'argomento, Nolan Lawson ha condiviso trucchi per misurare accuratamente le prestazioni del layout nel suo articolo e anche Jason Miller ha suggerito tecniche alternative. Abbiamo anche un piccolo articolo di Sergey Chikuyonok su come ottenere correttamente l'animazione della GPU.

    Animazioni ad alte prestazioni tra cui Posizione, Scala, Rotazione e Opacità
    I browser possono animare la trasformazione e l'opacità a buon mercato. Trigger CSS è utile per verificare se CSS attiva re-layout o reflow. (Credito immagine: Addy Osmani) (Anteprima grande)

    Nota : le modifiche ai livelli composti da GPU sono le meno costose, quindi se riesci a farla franca attivando solo la composizione tramite opacity e transform , sarai sulla strada giusta. Anche Anna Migas ha fornito molti consigli pratici nel suo intervento sul debug delle prestazioni di rendering dell'interfaccia utente. E per capire come eseguire il debug delle prestazioni della vernice in DevTools, controlla il video di controllo delle prestazioni della vernice di Umar.

  2. Hai ottimizzato per le prestazioni percepite?
    Sebbene la sequenza di come i componenti appaiono sulla pagina e la strategia di come serviamo le risorse al browser sono importanti, non dovremmo sottovalutare anche il ruolo delle prestazioni percepite. Il concetto si occupa degli aspetti psicologici dell'attesa, fondamentalmente mantenendo i clienti occupati o coinvolti mentre sta accadendo qualcos'altro. È qui che entrano in gioco la gestione della percezione, l'avvio preventivo, il completamento anticipato e la gestione della tolleranza.

    Che cosa significa tutto questo? Durante il caricamento delle risorse, possiamo cercare di essere sempre un passo avanti rispetto al cliente, in modo che l'esperienza sia rapida mentre succedono molte cose in background. Per mantenere il cliente impegnato, possiamo testare schermate dello scheletro (demo di implementazione) invece di caricare indicatori, aggiungere transizioni/animazioni e sostanzialmente imbrogliare l'UX quando non c'è più niente da ottimizzare.

    Nel loro caso di studio su The Art of UI Skeletons, Kumar McMillan condivide alcune idee e tecniche su come simulare elenchi dinamici, testo e schermo finale, oltre a come considerare il pensiero scheletrico con React.

    Attenzione però: gli schermi dello scheletro devono essere testati prima dell'implementazione poiché alcuni test hanno dimostrato che gli schermi dello scheletro possono avere le prestazioni peggiori in base a tutte le metriche.

  3. Impedite spostamenti di layout e ridipinture?
    Nel regno delle prestazioni percepite, probabilmente una delle esperienze più dirompenti è lo spostamento del layout , o reflow , causato da immagini e video ridimensionati, font Web, pubblicità iniettata o script scoperti in ritardo che popolano i componenti con contenuto reale. Di conseguenza, un cliente potrebbe iniziare a leggere un articolo solo per essere interrotto da un salto di layout sopra l'area di lettura. L'esperienza è spesso brusca e abbastanza disorientante: e questo è probabilmente un caso di priorità di caricamento che devono essere riconsiderate.

    La community ha sviluppato un paio di tecniche e soluzioni alternative per evitare reflow. In generale, è una buona idea evitare di inserire nuovi contenuti al di sopra dei contenuti esistenti , a meno che ciò non avvenga in risposta a un'interazione dell'utente. Imposta sempre gli attributi di larghezza e altezza sulle immagini, quindi i browser moderni assegnano la casella e riservano lo spazio per impostazione predefinita (Firefox, Chrome).

    Sia per le immagini che per i video, possiamo utilizzare un segnaposto SVG per riservare la casella di visualizzazione in cui apparirà il file multimediale. Ciò significa che l'area verrà riservata correttamente quando è necessario mantenere anche le sue proporzioni. Possiamo anche utilizzare segnaposto o immagini di riserva per annunci e contenuti dinamici, nonché slot di layout preassegnati.

    Invece di caricare lazy le immagini con script esterni, prendere in considerazione l'utilizzo del lazy-loading nativo o del lazy-loading ibrido quando carichiamo uno script esterno solo se il lazy-loading nativo non è supportato.

    Come accennato in precedenza, raggruppa sempre i ridisegni dei caratteri Web e passa da tutti i caratteri di fallback a tutti i caratteri Web contemporaneamente: assicurati solo che il passaggio non sia troppo brusco, regolando l'altezza della linea e la spaziatura tra i caratteri con il font-style-matcher .

    Per sovrascrivere le metriche dei caratteri per un carattere di riserva per emulare un carattere Web, possiamo utilizzare i descrittori @font-face per sovrascrivere le metriche dei caratteri (demo, abilitato in Chrome 87). (Si noti che le regolazioni sono complicate con pile di caratteri complicate.)

    Per i CSS tardivi, possiamo garantire che i CSS critici per il layout siano integrati nell'intestazione di ciascun modello. Anche oltre: per le pagine lunghe, quando viene aggiunta la barra di scorrimento verticale, sposta il contenuto principale di 16px a sinistra. Per visualizzare una barra di scorrimento in anticipo, possiamo aggiungere overflow-y: scroll su html per applicare una barra di scorrimento al primo disegno. Quest'ultimo aiuta perché le barre di scorrimento possono causare spostamenti di layout non banali a causa del riflusso del contenuto above the fold quando la larghezza cambia. Dovrebbe accadere principalmente su piattaforme con barre di scorrimento non sovrapposte come Windows. Ma: interrompe la position: sticky perché quegli elementi non scorreranno mai fuori dal contenitore.

    Se hai a che fare con intestazioni che diventano fisse o posizionate appiccicose nella parte superiore della pagina durante lo scorrimento, riserva spazio per l'intestazione quando diventa sbiadita, ad esempio con un elemento segnaposto o un margin-top sul contenuto. Un'eccezione dovrebbero essere i banner di consenso ai cookie che non dovrebbero avere impatto su CLS, ma a volte lo fanno: dipende dall'implementazione. Ci sono alcune strategie interessanti e takeaway in questo thread di Twitter.

    Per un componente di schede che potrebbe includere varie quantità di testo, puoi impedire i cambiamenti di layout con le pile di griglie CSS. Posizionando il contenuto di ciascuna scheda nella stessa area della griglia e nascondendone una alla volta, possiamo garantire che il contenitore occupi sempre l'altezza dell'elemento più grande, quindi non si verificheranno spostamenti di layout.

    Ah, e, naturalmente, lo scorrimento infinito e "Carica altro" possono causare anche spostamenti di layout se c'è contenuto sotto l'elenco (es. piè di pagina). Per migliorare CLS, riserva spazio sufficiente per il contenuto che verrebbe caricato prima che l'utente scorri fino a quella parte della pagina, rimuovi il piè di pagina o qualsiasi elemento DOM nella parte inferiore della pagina che potrebbe essere spinto verso il basso dal caricamento del contenuto. Inoltre, precarica i dati e le immagini per i contenuti below-the-fold in modo che quando un utente scorre così lontano, è già lì. Puoi utilizzare le librerie di virtualizzazione degli elenchi come react-window per ottimizzare anche elenchi lunghi ( grazie, Addy Osmani! ).

    Per garantire che l'impatto dei reflow sia contenuto, misurare la stabilità del layout con l'API Layout Instability. Con esso, puoi calcolare il punteggio Cumulative Layout Shift ( CLS ) e includerlo come requisito nei tuoi test, quindi ogni volta che viene visualizzata una regressione, puoi tracciarla e risolverla.

    Per calcolare il punteggio di spostamento del layout, il browser esamina le dimensioni della finestra e il movimento degli elementi instabili nella finestra tra due fotogrammi renderizzati. Idealmente, il punteggio sarebbe vicino a 0 . C'è un'ottima guida di Milica Mihajlija e Philip Walton su cos'è il CLS e come misurarlo. È un buon punto di partenza per misurare e mantenere le prestazioni percepite ed evitare interruzioni, soprattutto per le attività business-critical.

    Suggerimento rapido : per scoprire cosa ha causato un cambiamento di layout in DevTools, puoi esplorare i cambiamenti di layout in "Esperienza" nel pannello delle prestazioni.

    Bonus : se vuoi ridurre i reflow e le ridipinture, controlla la guida di Charis Theodoulou per ridurre al minimo il DOM Reflow/Layout Thrashing e l'elenco di Paul Irish di What force layout / reflow così come CSSTriggers.com, una tabella di riferimento sulle proprietà CSS che attivano il layout, paint e compositing.

Reti e HTTP/2

  1. La pinzatura OCSP è abilitata?
    Abilitando la pinzatura OCSP sul tuo server, puoi velocizzare i tuoi handshake TLS. L'Online Certificate Status Protocol (OCSP) è stato creato come alternativa al protocollo Certificate Revocation List (CRL). Entrambi i protocolli vengono utilizzati per verificare se un certificato SSL è stato revocato.

    Tuttavia, il protocollo OCSP non richiede al browser di dedicare tempo a scaricare e quindi cercare in un elenco le informazioni sui certificati, riducendo così il tempo necessario per un handshake.

  2. Hai ridotto l'impatto della revoca del certificato SSL?
    Nel suo articolo su "The Performance Cost of EV Certificates", Simon Hearne fornisce un'ottima panoramica dei certificati comuni e dell'impatto che la scelta di un certificato può avere sulle prestazioni complessive.

    Come scrive Simon, nel mondo dell'HTTPS esistono alcuni tipi di livelli di convalida dei certificati utilizzati per proteggere il traffico:

    • Domain Validation (DV) convalida che il richiedente del certificato possiede il dominio,
    • La convalida dell'organizzazione (OV) convalida che un'organizzazione possiede il dominio,
    • La convalida estesa (EV) convalida che un'organizzazione possiede il dominio, con una convalida rigorosa.

    È importante notare che tutti questi certificati sono gli stessi in termini di tecnologia; differiscono solo per le informazioni e le proprietà fornite in tali certificati.

    I certificati EV sono costosi e richiedono tempo in quanto richiedono a un essere umano di rivedere un certificato e garantirne la validità. I certificati DV, d'altra parte, sono spesso forniti gratuitamente, ad esempio da Let's Encrypt, un'autorità di certificazione aperta e automatizzata ben integrata in molti provider di hosting e CDN. In effetti, al momento in cui scriviamo, alimenta oltre 225 milioni di siti Web (PDF), sebbene rappresenti solo il 2,69% delle pagine (aperte in Firefox).

    Allora qual è il problema? Il problema è che i certificati EV non supportano completamente la graffatura OCSP sopra menzionata. Mentre la pinzatura consente al server di verificare con l'Autorità di certificazione se il certificato è stato revocato e quindi aggiungere ("pinzatura") queste informazioni al certificato, senza pinzare il client deve fare tutto il lavoro, risultando in richieste non necessarie durante la negoziazione TLS . In caso di connessioni scadenti, ciò potrebbe comportare notevoli costi di prestazioni (oltre 1000 ms).

    I certificati EV non sono un'ottima scelta per le prestazioni web e possono causare un impatto molto maggiore sulle prestazioni rispetto ai certificati DV. Per prestazioni Web ottimali, fornisci sempre un certificato DV pinzato OCSP. Sono anche molto più economici dei certificati EV e meno seccature da acquisire. Bene, almeno fino a quando CRLite non sarà disponibile.

    Un grafico che mostra il numero di handshake lungo i datagrammi UDP in caso di dati semplici, compressi o entrambi
    La compressione è importante: il 40–43% delle catene di certificati non compresse è troppo grande per adattarsi a un singolo volo QUIC di 3 datagrammi UDP. (Credito immagine:) Velocemente) (Grande anteprima)

    Nota : con QUIC/HTTP/3 alle porte, vale la pena notare che la catena di certificati TLS è l'unico contenuto di dimensioni variabili che domina il conteggio dei byte nell'handshake QUIC. La dimensione varia tra poche centinaia di bye e oltre 10 KB.

    Quindi mantenere i certificati TLS piccoli è molto importante su QUIC/HTTP/3, poiché i certificati di grandi dimensioni causeranno più handshake. Inoltre, dobbiamo assicurarci che i certificati siano compressi, altrimenti le catene di certificati sarebbero troppo grandi per adattarsi a un singolo volo QUIC.

    Puoi trovare molti più dettagli e indicazioni al problema e alle soluzioni su:

    • I certificati EV rendono il Web lento e inaffidabile di Aaron Peters,
    • L'impatto della revoca del certificato SSL sulle prestazioni web da parte di Matt Hobbs,
    • Il costo delle prestazioni dei certificati EV di Simon Hearne,
    • L'handshake QUIC richiede una compressione veloce? di Patrick McManus.
  3. Hai già adottato IPv6?
    Poiché lo spazio è esaurito con IPv4 e le principali reti mobili stanno adottando IPv6 rapidamente (gli Stati Uniti hanno quasi raggiunto una soglia di adozione di IPv6 del 50%), è una buona idea aggiornare il tuo DNS a IPv6 per rimanere a prova di proiettile per il futuro. Assicurati solo che il supporto dual-stack sia fornito attraverso la rete: consente a IPv6 e IPv4 di funzionare simultaneamente l'uno accanto all'altro. Dopotutto, IPv6 non è compatibile con le versioni precedenti. Inoltre, gli studi dimostrano che IPv6 ha reso questi siti Web dal 10 al 15% più veloci grazie alla scoperta dei vicini (NDP) e all'ottimizzazione del percorso.
  4. Assicurati che tutte le risorse vengano eseguite su HTTP/2 (o HTTP/3).
    Con Google che negli ultimi anni ha spinto verso un Web HTTPS più sicuro, il passaggio all'ambiente HTTP/2 è sicuramente un buon investimento. Infatti, secondo Web Almanac, il 64% di tutte le richieste viene già eseguito su HTTP/2.

    È importante capire che HTTP/2 non è perfetto e presenta problemi di priorità, ma è supportato molto bene; e, nella maggior parte dei casi, è meglio per te.

    Un avvertimento: HTTP/2 Server Push è stato rimosso da Chrome, quindi se la tua implementazione si basa su Server Push, potrebbe essere necessario rivisitarlo. Invece, potremmo guardare gli Early Hints, che sono già integrati come esperimento in Fastly.

    Se sei ancora in esecuzione su HTTP, l'attività più dispendiosa in termini di tempo sarà prima migrare a HTTPS, quindi regolare il processo di compilazione per soddisfare il multiplexing e la parallelizzazione HTTP/2. Portare HTTP/2 su Gov.uk è un fantastico case study su come fare proprio questo, trovare un modo attraverso CORS, SRI e WPT lungo il percorso. Per il resto di questo articolo, presupponiamo che tu stia passando o sia già passato a HTTP/2.

Un grafico che mostra le serie temporali delle richieste HTTP/2 sia su desktop che su dispositivi mobili dal 2 gennaio 2016 al 1 ottobre 2020
Il 64% di tutte le richieste viene servito su HTTP/2 alla fine del 2020, secondo Web Almanac, a soli 4 anni dalla sua standardizzazione formale. (Fonte immagine: Web Almanac) (Anteprima grande)
  1. Distribuire correttamente HTTP/2.
    Anche in questo caso, servire le risorse su HTTP/2 può trarre vantaggio da una revisione parziale di come hai servito le risorse finora. Dovrai trovare un giusto equilibrio tra l'imballaggio dei moduli e il caricamento di molti piccoli moduli in parallelo. Alla fine della giornata, la migliore richiesta non è ancora la richiesta, tuttavia, l'obiettivo è trovare un buon equilibrio tra la prima rapida consegna degli asset e la memorizzazione nella cache.

    Da un lato, potresti voler evitare di concatenare del tutto le risorse, invece di scomporre l'intera interfaccia in tanti piccoli moduli, comprimerli come parte del processo di compilazione e caricarli in parallelo. Una modifica in un file non richiede il download dell'intero foglio di stile o JavaScript. Inoltre, riduce al minimo il tempo di analisi e mantiene bassi i payload delle singole pagine.

    D'altra parte, l'imballaggio è ancora importante. Utilizzando molti piccoli script, la compressione complessiva ne risentirà e aumenterà il costo del recupero degli oggetti dalla cache. La compressione di un pacchetto di grandi dimensioni trarrà vantaggio dal riutilizzo del dizionario, mentre i pacchetti separati piccoli non lo faranno. C'è un lavoro standard per affrontarlo, ma per ora è lontano. In secondo luogo, i browser non sono ancora stati ottimizzati per tali flussi di lavoro. Ad esempio, Chrome attiverà le comunicazioni tra processi (IPC) lineari rispetto al numero di risorse, quindi includere centinaia di risorse avrà costi di runtime del browser.

    Codice HTML tramite caricamento CSS progressivo
    Per ottenere i migliori risultati con HTTP/2, considera di caricare i CSS progressivamente, come suggerito da Jake Archibald di Chrome.

    Tuttavia, puoi provare a caricare i CSS progressivamente. In effetti, il CSS interno non blocca più il rendering per Chrome. Ma ci sono alcuni problemi di priorità, quindi non è così semplice, ma vale la pena sperimentare.

    Potresti farla franca con la coalescenza della connessione HTTP/2, che ti consente di utilizzare il partizionamento orizzontale del dominio beneficiando di HTTP/2, ma raggiungerlo in pratica è difficile e, in generale, non è considerata una buona pratica. Inoltre, HTTP/2 e Integrità delle sottorisorse non vanno sempre d'accordo.

    Cosa fare? Bene, se stai utilizzando HTTP/2, inviare circa 6-10 pacchetti sembra un compromesso decente (e non è male per i browser legacy). Sperimenta e misura per trovare il giusto equilibrio per il tuo sito web.

  2. Inviamo tutte le risorse su una singola connessione HTTP/2?
    Uno dei principali vantaggi di HTTP/2 è che ci consente di inviare risorse via cavo su una singola connessione. Tuttavia, a volte potremmo aver fatto qualcosa di sbagliato, ad esempio avere un problema con CORS o configurato in modo errato l'attributo crossorigin , quindi il browser sarebbe costretto ad aprire una nuova connessione.

    Per verificare se tutte le richieste utilizzano una singola connessione HTTP/2 o qualcosa non è configurato correttamente, abilita la colonna "ID connessione" in DevTools → Rete. Ad esempio, qui tutte le richieste condividono la stessa connessione (286), tranne manifest.json, che ne apre una separata (451).

Uno screenshot di DevTools si apre nel browser Chrome
Tutte le richieste condividono la stessa connessione HTTP/2 (286), ad eccezione di manifest.json, che ne apre una separata (451). via Iamakulov. (Grande anteprima)
  1. I tuoi server e CDN supportano HTTP/2?
    Server e CDN diversi (ancora) supportano HTTP/2 in modo diverso. Usa Confronto CDN per controllare le tue opzioni o cercare rapidamente le prestazioni dei tuoi server e le funzionalità che puoi aspettarti di essere supportate.

    Consulta l'incredibile ricerca di Pat Meenan sulle priorità HTTP/2 (video) e verifica il supporto del server per la definizione delle priorità HTTP/2. Secondo Pat, si consiglia di abilitare il controllo della congestione BBR e impostare tcp_notsent_lowat su 16 KB affinché la priorità HTTP/2 funzioni in modo affidabile su kernel Linux 4.9 e versioni successive ( grazie, Yoav! ). Andy Davies ha svolto una ricerca simile per la definizione delle priorità HTTP/2 su browser, CDN e servizi di hosting cloud.

    Mentre ci sei, ricontrolla se il tuo kernel supporta TCP BBR e abilitalo se possibile. Attualmente è utilizzato su Google Cloud Platform, Amazon Cloudfront, Linux (es. Ubuntu).

  2. È in uso la compressione HPACK?
    Se stai utilizzando HTTP/2, verifica che i tuoi server implementino la compressione HPACK per le intestazioni di risposta HTTP per ridurre il sovraccarico non necessario. Alcuni server HTTP/2 potrebbero non supportare completamente la specifica, ad esempio HPACK. H2spec è un ottimo strumento (anche se molto tecnicamente dettagliato) per verificarlo. L'algoritmo di compressione di HPACK è piuttosto impressionante e funziona.
  3. Assicurati che la sicurezza sul tuo server sia a prova di proiettile.
    Tutte le implementazioni del browser di HTTP/2 vengono eseguite su TLS, quindi probabilmente vorrai evitare avvisi di sicurezza o alcuni elementi della tua pagina non funzionano. Ricontrolla che le tue intestazioni di sicurezza siano impostate correttamente, elimina le vulnerabilità note e controlla la tua configurazione HTTPS.

    Inoltre, assicurati che tutti i plug-in esterni e gli script di monitoraggio siano caricati tramite HTTPS, che non sia possibile eseguire script tra siti e che sia le intestazioni HTTP Strict Transport Security che le intestazioni dei criteri di sicurezza dei contenuti siano impostate correttamente.

  4. I tuoi server e CDN supportano HTTP/3?
    Sebbene HTTP/2 abbia apportato una serie di significativi miglioramenti delle prestazioni al Web, ha anche lasciato una certa area di miglioramento, in particolare il blocco dell'intestazione in TCP, che era evidente su una rete lenta con una significativa perdita di pacchetti. HTTP/3 risolve definitivamente questi problemi (articolo).

    Per risolvere i problemi di HTTP/2, IETF, insieme a Google, Akamai e altri, ha lavorato su un nuovo protocollo che è stato recentemente standardizzato come HTTP/3.

    Robin Marx ha spiegato molto bene HTTP/3 e la seguente spiegazione si basa sulla sua spiegazione. Nel suo nucleo, HTTP/3 è molto simile a HTTP/2 in termini di funzionalità, ma sotto il cofano funziona in modo molto diverso. HTTP/3 offre una serie di miglioramenti: handshake più veloci, migliore crittografia, flussi indipendenti più affidabili, migliore crittografia e controllo del flusso. Una differenza notevole è che HTTP/3 utilizza QUIC come livello di trasporto, con pacchetti QUIC incapsulati sopra i diagrammi UDP, anziché TCP.

    QUIC integra completamente TLS 1.3 nel protocollo, mentre in TCP è sovrapposto. Nel tipico stack TCP, abbiamo alcuni tempi di andata e ritorno di sovraccarico perché TCP e TLS devono eseguire i propri handshake separati, ma con QUIC entrambi possono essere combinati e completati in un solo viaggio di andata e ritorno . Poiché TLS 1.3 ci consente di impostare chiavi di crittografia per una connessione successiva, dalla seconda connessione in poi, possiamo già inviare e ricevere dati a livello di applicazione nel primo round trip, che si chiama "0-RTT".

    Inoltre, l'algoritmo di compressione dell'intestazione di HTTP/2 è stato interamente riscritto, insieme al suo sistema di definizione delle priorità. Inoltre, QUIC supporta la migrazione della connessione dal Wi-Fi alla rete cellulare tramite gli ID di connessione nell'intestazione di ciascun pacchetto QUIC. La maggior parte delle implementazioni viene eseguita nello spazio utente, non nello spazio del kernel (come avviene con TCP), quindi dovremmo aspettarci che il protocollo si evolva in futuro.

    Tutto farebbe una grande differenza? Probabilmente sì, soprattutto influendo sui tempi di caricamento sui dispositivi mobili, ma anche sul modo in cui serviamo le risorse agli utenti finali. Mentre in HTTP/2, più richieste condividono una connessione, in HTTP/3 anche le richieste condividono una connessione ma trasmettono in modo indipendente, quindi un pacchetto eliminato non influisce più su tutte le richieste, ma solo su un flusso.

    Ciò significa che mentre con un pacchetto JavaScript di grandi dimensioni l'elaborazione delle risorse verrà rallentata quando un flusso si interrompe, l'impatto sarà meno significativo quando più file vengono trasmessi in streaming in parallelo (HTTP/3). Quindi l'imballaggio è ancora importante .

    HTTP/3 è ancora in lavorazione. Chrome, Firefox e Safari hanno già implementazioni. Alcuni CDN supportano già QUIC e HTTP/3. Alla fine del 2020, Chrome ha iniziato a distribuire HTTP/3 e IETF QUIC, e infatti tutti i servizi Google (Google Analytics, YouTube ecc.) sono già in esecuzione su HTTP/3. LiteSpeed ​​Web Server supporta HTTP/3, ma né Apache, nginx o IIS lo supportano ancora, ma è probabile che cambi rapidamente nel 2021.

    In conclusione : se hai un'opzione per utilizzare HTTP/3 sul server e sulla tua CDN, è probabilmente un'ottima idea farlo. Il vantaggio principale verrà dal recupero simultaneo di più oggetti, specialmente su connessioni ad alta latenza. Non lo sappiamo ancora con certezza poiché non ci sono molte ricerche fatte in quello spazio, ma i primi risultati sono molto promettenti.

    Se vuoi approfondire le specifiche e i vantaggi del protocollo, ecco alcuni buoni punti di partenza da verificare:

    • HTTP/3 Explained, uno sforzo collaborativo per documentare i protocolli HTTP/3 e QUIC. Disponibile in varie lingue, anche in PDF.
    • Migliorare le prestazioni Web con HTTP/3 con Daniel Stenberg.
    • Una guida accademica a QUIC con Robin Marx introduce i concetti di base dei protocolli QUIC e HTTP/3, spiega come HTTP/3 gestisce il blocco dell'intestazione e la migrazione delle connessioni e come HTTP/3 è progettato per essere sempreverde (grazie, Simon !).
    • Puoi controllare se il tuo server è in esecuzione su HTTP/3 su HTTP3Check.net.

Test e monitoraggio

  1. Hai ottimizzato il flusso di lavoro di auditing?
    Potrebbe non sembrare un grosso problema, ma avere le giuste impostazioni a portata di mano potrebbe farti risparmiare un bel po' di tempo nei test. Prendi in considerazione l'utilizzo di Alfred Workflow per WebPageTest di Tim Kadlec per inviare un test all'istanza pubblica di WebPageTest. In effetti, WebPageTest ha molte caratteristiche oscure, quindi prenditi il ​​tempo necessario per imparare a leggere un grafico di visualizzazione a cascata di WebPageTest e come leggere un grafico di visualizzazione di connessione di WebPageTest per diagnosticare e risolvere più rapidamente i problemi di prestazioni.

    Puoi anche guidare WebPageTest da un foglio di calcolo di Google e incorporare accessibilità, prestazioni e punteggi SEO nella tua configurazione di Travis con Lighthouse CI o direttamente in Webpack.

    Dai un'occhiata a AutoWebPerf recentemente rilasciato, uno strumento modulare che consente la raccolta automatica di dati sulle prestazioni da più origini. Ad esempio, potremmo impostare un test giornaliero sulle tue pagine critiche per acquisire i dati sul campo dall'API CrUX e i dati di laboratorio da un report Lighthouse di PageSpeed ​​Insights.

    E se hai bisogno di eseguire rapidamente il debug di qualcosa ma il tuo processo di compilazione sembra essere notevolmente lento, tieni presente che "la rimozione degli spazi bianchi e la manipolazione dei simboli rappresentano il 95% della riduzione delle dimensioni nel codice minimizzato per la maggior parte di JavaScript, non elaborare le trasformazioni del codice. Puoi disabilita semplicemente la compressione per velocizzare le build di Uglify da 3 a 4 volte."

Uno screenshot della notifica della richiesta pull di GitHub in cui si afferma che è necessaria la revisione e che l'unione è bloccata fino a quando i controlli non sono stati risolti con successo
L'integrazione di accessibilità, prestazioni e punteggi SEO nella configurazione di Travis con Lighthouse CI metterà in evidenza l'impatto sulle prestazioni di una nuova funzionalità per tutti gli sviluppatori che contribuiscono. (Fonte immagine) (Anteprima grande)
  1. Hai testato in browser proxy e browser legacy?
    I test su Chrome e Firefox non sono sufficienti. Guarda come funziona il tuo sito web nei browser proxy e nei browser legacy. UC Browser e Opera Mini, ad esempio, detengono una quota di mercato significativa in Asia (fino al 35% in Asia). Misura la velocità media di Internet nei tuoi paesi di interesse per evitare grandi sorprese lungo la strada. Testare con la limitazione della rete ed emulare un dispositivo con DPI elevati. BrowserStack è fantastico per i test su dispositivi reali remoti e integralo anche con almeno alcuni dispositivi reali nel tuo ufficio: ne vale la pena.
  1. Hai testato le prestazioni delle tue 404 pagine?
    Normalmente non ci pensiamo due volte quando si tratta di 404 pagine. Dopotutto, quando un client richiede una pagina che non esiste sul server, il server risponderà con un codice di stato 404 e la pagina 404 associata. Non c'è molto da fare, vero?

    Un aspetto importante di 404 risposte è la dimensione effettiva del corpo della risposta che viene inviata al browser. Secondo la ricerca di 404 pagine di Matt Hobbs, la stragrande maggioranza delle 404 risposte proviene da favicon mancanti, richieste di caricamento di WordPress, richieste JavaScript non funzionanti, file manifest nonché file CSS e font. Ogni volta che un cliente richiede una risorsa che non esiste, riceverà una risposta 404 e spesso tale risposta è enorme.

    Assicurati di esaminare e ottimizzare la strategia di memorizzazione nella cache per le tue 404 pagine. Il nostro obiettivo è fornire HTML al browser solo quando si aspetta una risposta HTML e restituire un piccolo errore di payload per tutte le altre risposte. Secondo Matt, "se mettiamo una CDN davanti alla nostra origine, abbiamo la possibilità di memorizzare nella cache la risposta della pagina 404 sulla CDN. Questo è utile perché senza di essa, colpire una pagina 404 potrebbe essere utilizzato come vettore di attacco DoS, da costringendo il server di origine a rispondere a ogni richiesta 404 anziché lasciare che la CDN risponda con una versione memorizzata nella cache."

    Gli errori 404 non solo possono danneggiare le tue prestazioni, ma possono anche costare traffico, quindi è una buona idea includere una pagina di errore 404 nella suite di test di Lighthouse e tenerne traccia nel tempo.

  2. Hai testato le prestazioni delle tue richieste di consenso GDPR?
    In tempi di GDPR e CCPA, è diventato comune affidarsi a terze parti per fornire opzioni ai clienti dell'UE per accettare o rifiutare il monitoraggio. Tuttavia, come con qualsiasi altro script di terze parti, le loro prestazioni possono avere un impatto piuttosto devastante sull'intero sforzo di prestazioni.

    Naturalmente, è probabile che il consenso effettivo cambi l'impatto degli script sulle prestazioni complessive, quindi, come ha notato Boris Schapira, potremmo voler studiare alcuni profili di prestazioni web diversi:

    • Il consenso è stato completamente rifiutato,
    • Il consenso è stato parzialmente rifiutato,
    • Il consenso è stato interamente dato.
    • L'utente non ha agito alla richiesta di consenso (o la richiesta è stata bloccata da un blocco dei contenuti),

    Normalmente le richieste di consenso ai cookie non dovrebbero avere un impatto su CLS, ma a volte lo fanno, quindi prendi in considerazione l'utilizzo di opzioni gratuite e open source Osano o cookie-consent-box.

    In generale, vale la pena esaminare le prestazioni del popup poiché sarà necessario determinare l'offset orizzontale o verticale dell'evento del mouse e posizionare correttamente il popup rispetto all'ancora. Noam Rosenthal condivide gli insegnamenti del team di Wikimedia nell'articolo Case study sulle prestazioni Web: anteprime della pagina di Wikipedia (disponibili anche come video e minuti).

  3. Mantieni un CSS di diagnostica delle prestazioni?
    Sebbene possiamo includere tutti i tipi di controlli per garantire che il codice non performante venga distribuito, spesso è utile avere una rapida idea di alcuni dei frutti a basso impatto che potrebbero essere risolti facilmente. Per questo, potremmo usare il brillante Performance Diagnostics CSS di Tim Kadlec (ispirato allo snippet di Harry Roberts che mette in evidenza immagini caricate pigre, immagini non dimensionate, immagini in formato legacy e script sincroni.

    Ad esempio, potresti voler assicurarti che nessuna immagine above the fold venga caricata in modo pigro. È possibile personalizzare lo snippet in base alle proprie esigenze, ad esempio per evidenziare i caratteri Web non utilizzati o per rilevare i caratteri delle icone. Un piccolo grande strumento per garantire che gli errori siano visibili durante il debug o semplicemente per controllare il progetto corrente molto rapidamente.

    /* Performance Diagnostics CSS */ /* via Harry Roberts. https://twitter.com/csswizardry/status/1346477682544951296 */ img[loading=lazy] { outline: 10px solid red; }
  1. Hai testato l'impatto sull'accessibilità?
    Quando il browser inizia a caricare una pagina, crea un DOM e, se è presente una tecnologia assistiva come uno screen reader in esecuzione, crea anche un albero di accessibilità. L'utilità per la lettura dello schermo deve quindi interrogare l'albero di accessibilità per recuperare le informazioni e renderle disponibili all'utente, a volte per impostazione predefinita ea volte su richiesta. E a volte ci vuole tempo.

    Quando si parla di Time to Interactive veloce, di solito si intende un indicatore di quanto presto un utente può interagire con la pagina facendo clic o toccando collegamenti e pulsanti. Il contesto è leggermente diverso con gli screen reader. In tal caso, Time to Interactive veloce indica quanto tempo passa prima che l'utilità per la lettura dello schermo possa annunciare la navigazione su una determinata pagina e un utente dell'utilità per la lettura dello schermo può effettivamente premere la tastiera per interagire.

    Leonie Watson ha tenuto un discorso illuminante sulle prestazioni di accessibilità e in particolare sull'impatto che il caricamento lento ha sui ritardi degli annunci degli screen reader. Le utilità per la lettura dello schermo sono utilizzate per annunci veloci e navigazione rapida e quindi potrebbero essere potenzialmente anche meno pazienti degli utenti vedenti.

    Le pagine di grandi dimensioni e le manipolazioni DOM con JavaScript causeranno ritardi negli annunci degli screen reader. Un'area piuttosto inesplorata che potrebbe richiedere un po' di attenzione e test poiché gli screen reader sono disponibili letteralmente su ogni piattaforma (Jaws, NVDA, Voiceover, Narrator, Orca).

  2. È previsto un monitoraggio continuo?
    Avere un'istanza privata di WebPagetest è sempre vantaggioso per test rapidi e illimitati. Tuttavia, uno strumento di monitoraggio continuo, come Sitespeed, Calibre e SpeedCurve, con avvisi automatici ti darà un quadro più dettagliato delle tue prestazioni. Imposta i tuoi indicatori di temporizzazione utente per misurare e monitorare metriche specifiche dell'azienda. Inoltre, prendi in considerazione l'aggiunta di avvisi di regressione delle prestazioni automatizzati per monitorare le modifiche nel tempo.

    Cerca di utilizzare le soluzioni RUM per monitorare i cambiamenti nelle prestazioni nel tempo. Per strumenti di test di carico automatizzati simili a unit test, puoi usare k6 con la sua API di scripting. Inoltre, controlla SpeedTracker, Lighthouse e Calibre.

Vittorie veloci

Questo elenco è abbastanza completo e il completamento di tutte le ottimizzazioni potrebbe richiedere un po' di tempo. Quindi, se avessi solo 1 ora per ottenere miglioramenti significativi, cosa faresti? Riduciamo il tutto a 17 frutti bassi . Ovviamente, prima di iniziare e una volta terminato, misurare i risultati, tra cui Largest Contentful Paint e Time To Interactive su una connessione 3G e via cavo.

  1. Misurare l'esperienza del mondo reale e fissare obiettivi appropriati. Cerca di essere almeno il 20% più veloce del tuo concorrente più veloce. Rimani entro il più grande contenuto di pittura < 2,5 s, un primo ritardo di input < 100 ms, tempo per interattivo < 5 s su 3G lento, per visite ripetute, TTI < 2 s. Ottimizza almeno per First Contentful Paint e Time To Interactive.
  2. Ottimizza le immagini con Squoosh, mozjpeg, guetzli, pingo e SVGOMG e servi AVIF/WebP con un CDN di immagini.
  3. Prepara CSS critici per i tuoi modelli principali e incorporali nella <head> di ogni modello. Per CSS/JS, operare entro un budget di dimensioni file critiche di max. 170 KB compressi con gzip (0,7 MB decompressi).
  4. Taglia, ottimizza, rinvia e carica in modo lento gli script. Investi nella configurazione del tuo bundler per rimuovere le ridondanze e controllare alternative leggere.
  5. Ospita sempre autonomamente le tue risorse statiche e preferisci sempre ospitare autonomamente risorse di terze parti. Limita l'impatto di script di terze parti. Usa le facciate, carica i widget sull'interazione e fai attenzione agli snippet anti-sfarfallio.
  6. Sii selettivo quando scegli un framework. Per le applicazioni a pagina singola, identifica le pagine critiche e servile in modo statico, o almeno esegui il prerendering e usa l'idratazione progressiva a livello di componente e importa i moduli sull'interazione.
  7. Il rendering lato client da solo non è una buona scelta per le prestazioni. Effettua il prerendering se le tue pagine non cambiano molto e rimanda l'avvio dei framework se puoi. Se possibile, usa il rendering lato server in streaming.
  8. Fornisci codice legacy solo a browser legacy con <script type="module"> e pattern module/nomodule.
  9. Sperimenta il raggruppamento delle regole CSS e testa il CSS interno.
  10. Aggiungi suggerimenti sulle risorse per velocizzare la consegna con dns-lookup , preconnect , prefetch , preload e prerender più rapidi.
  11. Sottoimposta i caratteri Web e caricali in modo asincrono e utilizza font-display in CSS per un primo rendering rapido.
  12. Verifica che le intestazioni della cache HTTP e le intestazioni di sicurezza siano impostate correttamente.
  13. Abilita la compressione Brotli sul server. (Se ciò non è possibile, assicurati almeno che la compressione Gzip sia abilitata.)
  14. Abilita la congestione TCP BBR fintanto che il tuo server è in esecuzione sul kernel Linux versione 4.9+.
  15. Abilita la pinzatura OCSP e IPv6, se possibile. Servi sempre un certificato DV pinzato OCSP.
  16. Abilita la compressione HPACK per HTTP/2 e passa a HTTP/3 se disponibile.
  17. Memorizza nella cache risorse come font, stili, JavaScript e immagini in una cache di servizio.

Scarica la lista di controllo (PDF, pagine Apple)

Con questa checklist in mente, dovresti essere preparato per qualsiasi tipo di progetto di performance front-end. Sentiti libero di scaricare il PDF pronto per la stampa dell'elenco di controllo e un documento Apple Pages modificabile per personalizzare l'elenco di controllo in base alle tue esigenze:

  • Scarica la checklist PDF (PDF, 166 KB)
  • Scarica la checklist in Apple Pages (.pages, 275 KB)
  • Scarica la checklist in MS Word (.docx, 151 KB)

Se hai bisogno di alternative, puoi anche controllare la checklist front-end di Dan Rublic, la "Designer's Web Performance Checklist" di Jon Yablonski e la FrontendChecklist.

Si parte!

Alcune delle ottimizzazioni potrebbero andare oltre l'ambito del tuo lavoro o budget o potrebbero essere semplicemente eccessive dato il codice legacy con cui devi fare i conti. Va bene! Usa questo elenco di controllo come guida generale (e si spera esauriente) e crea il tuo elenco di problemi che si applicano al tuo contesto. Ma soprattutto, testa e misura i tuoi progetti per identificare i problemi prima dell'ottimizzazione. Buoni risultati delle prestazioni nel 2021, a tutti!


Un enorme ringraziamento a Guy Podjarny, Yoav Weiss, Addy Osmani, Artem Denysov, Denys Mishunov, Ilya Pukhalski, Jeremy Wagner, Colin Bendell, Mark Zeman, Patrick Meenan, Leonardo Losoviz, Andy Davies, Rachel Andrew, Anselm Hannemann, Barry Pollard, Patrick Hamann, Gideon Pyzer, Andy Davies, Maria Prosvernina, Tim Kadlec, Rey Bango, Matthias Ott, Peter Bowyer, Phil Walton, Mariana Peralta, Pepijn Senders, Mark Nottingham, Jean Pierre Vincent, Philipp Tellis, Ryan Townsend, Ingrid Bergman, Mohamed Hussain SH, Jacob Groß, Tim Swalling, Bob Visser, Kev Adamson, Adir Amsalem, Aleksey Kulikov e Rodney Rehm per aver recensito questo articolo, così come la nostra fantastica community che ha condiviso le tecniche e le lezioni apprese dal suo lavoro nell'ottimizzazione delle prestazioni affinché tutti possano utilizzarle . Sei davvero strepitoso!