Ottimizza il caricamento delle risorse

Nel modulo precedente, alcuni concetti alla base del percorso di rendering critico erano e come le risorse di blocco della visualizzazione e di blocco dei parser possano ritardare rendering iniziale della pagina. Ora che conosci alcuni dei concetti alla base a questo punto, sarai pronto ad apprendere alcune tecniche per ottimizzare i il percorso di rendering.

Durante il caricamento di una pagina, all'interno del codice HTML viene fatto riferimento a molte risorse che forniscono una pagina con il suo aspetto e layout tramite CSS, nonché la sua interattività tramite JavaScript. In questo modulo vengono trattati una serie di concetti importanti queste risorse e il modo in cui influiscono sul tempo di caricamento di una pagina.

Blocco del rendering

Come discusso nel modulo precedente, il CSS è una risorsa di render-blocking, in quanto impedisce al browser di eseguire il rendering di qualsiasi contenuto fino a quando il modello a oggetti CSS (CSSOM). Il browser blocca il rendering per impedire la visualizzazione di Flash di Contenuti senza stile (FOUC), contenuti indesiderati dal punto di vista dell'esperienza utente.

Nel video precedente, c'è un breve FOUC in cui potete visualizzare la pagina senza con qualsiasi stile. Successivamente, tutti gli stili vengono applicati una volta che il CSS della pagina ha terminato il caricamento dalla rete e la versione senza stile della pagina immediatamente sostituita con la versione con stile.

In generale, il FOUC è qualcosa che normalmente non si vede, ma il concetto è importante capire, in modo da sapere il perché il browser blocca il rendering della pagina fino a quando il CSS non viene scaricato e applicato alla pagina. Blocco del rendering non è necessariamente indesiderato, ma vuoi ridurne al minimo la durata mantenendo il CSS ottimizzato.

Blocco del parser

Una risorsa di blocco del parser interrompe l'analizzatore sintattico HTML, ad esempio un <script> elemento senza attributi async o defer. Quando il parser rileva un <script>, il browser deve valutare ed eseguire lo script prima e proseguirà con l'analisi del resto del codice HTML. Ciò è dovuto alla progettazione, poiché gli script modificare o accedere al DOM per un certo periodo di tempo mentre è ancora in fase di creazione.

<!-- This is a parser-blocking script: -->
<script src="/script.js"></script>

Quando utilizzi file JavaScript esterni (senza async o defer), l'analizzatore sintattico viene bloccato dal rilevamento del file fino al suo download, analisi e eseguito. Quando utilizzi JavaScript in linea, l'analizzatore sintattico viene bloccato in modo simile finché lo script incorporato viene analizzato ed eseguito.

.

Lo scanner di precaricamento

Lo scanner di precaricamento è un'ottimizzazione del browser sotto forma di codice HTML secondario. parser che analizza la risposta HTML non elaborata per trovare e recuperare in modo speculativo prima che l'analizzatore sintattico HTML principale le rilevi. Per Ad esempio, lo scanner di precaricamento consente al browser di avviare il download di un risorsa specificata in un elemento <img>, anche quando l'analizzatore sintattico HTML è bloccato durante il recupero e l'elaborazione di risorse come CSS e JavaScript.

Per poter sfruttare lo scanner di precaricamento, è necessario includere risorse critiche nel markup HTML inviato dal server. I seguenti pattern di caricamento delle risorse sono non rilevabili dallo scanner di precaricamento:

  • Immagini caricate da CSS utilizzando la proprietà background-image. Queste immagini i riferimenti sono in CSS e non possono essere rilevati dallo scanner di precaricamento.
  • Script caricati dinamicamente sotto forma di markup dell'elemento <script> inserito nel DOM utilizzando JavaScript o i moduli caricati mediante import() dinamico.
  • HTML visualizzato sul client tramite JavaScript. Tale markup è contenuto in stringhe nelle risorse JavaScript e non è rilevabile dal precaricamento scanner.
  • Dichiarazioni @import del CSS.

Questi pattern di caricamento delle risorse sono tutte risorse scoperte in ritardo e, di conseguenza, non sfruttano lo scanner di precaricamento. Evitali ogni volta che è possibile. Se evitare questi pattern non è possibile, ma potresti essere in grado di utilizzare una Suggerimento preload per evitare ritardi nel rilevamento delle risorse.

CSS

CSS determina la presentazione e il layout di una pagina. Come descritto in precedenza, è una risorsa che blocca la visualizzazione, quindi l'ottimizzazione del CSS potrebbe comportare impatto sul tempo di caricamento complessivo della pagina.

Minimizzazione

Minimizzando i file CSS riduce le dimensioni di una risorsa CSS, il che aumenta il download. Ciò si ottiene principalmente rimuovendo contenuti da un file CSS di origine, come spazi e altri caratteri invisibili, e la generazione il risultato in un file appena ottimizzato:

/* Unminified CSS: */

/* Heading 1 */
h1 {
  font-size: 2em;
  color: #000000;
}

/* Heading 2 */
h2 {
  font-size: 1.5em;
  color: #000000;
}
/* Minified CSS: */
h1,h2{color:#000}h1{font-size:2em}h2{font-size:1.5em}

Nella sua forma più semplice, la minimizzazione del CSS è un'ottimizzazione efficace che potrebbe migliorare il valore FCP del sito web e, in alcuni casi, anche l'LCP. Strumenti come i bundle possono eseguire automaticamente questa ottimizzazione per te in produzione le build.

Rimuovi CSS inutilizzato

Prima di eseguire il rendering dei contenuti, il browser deve scaricare e analizzare tutti fogli di stile. Il tempo necessario per completare l'analisi include anche gli stili che inutilizzati nella pagina corrente. Se utilizzi un bundler che combina tutti i CSS risorse in un unico file, è probabile che gli utenti scarichino più CSS di necessari per il rendering della pagina corrente.

Per scoprire il CSS inutilizzato per la pagina corrente, utilizza lo strumento Copertura in Chrome DevTools.

Uno screenshot dello strumento Copertura in Chrome DevTools. Nel riquadro inferiore viene selezionato un file CSS che mostra una notevole quantità di CSS inutilizzato dal layout della pagina corrente.
. Lo strumento di copertura in Chrome DevTools è utile per rilevare i CSS (e JavaScript) non utilizzato dalla pagina corrente. Può essere utilizzato per suddividere i file CSS in più risorse affinché possano essere caricate da pagine diverse, invece di spedire un bundle CSS molto più grande che può ritardare il rendering della pagina.

La rimozione dello spazio CSS inutilizzato ha un duplice effetto: oltre a ridurre la quantità di download tempo, stai ottimizzando la creazione dell'albero di rendering, in quanto il browser deve elaborare meno regole CSS.

Evita le dichiarazioni @import del CSS

Anche se può sembrare pratico, dovresti evitare le dichiarazioni @import in CSS:

/* Don't do this: */
@import url('style.css');

Analogamente al funzionamento dell'elemento <link> in HTML, la dichiarazione @import in CSS consente di importare una risorsa CSS esterna da un foglio di stile. La la differenza principale tra questi due approcci è che l'elemento <link> HTML fa parte della risposta HTML e viene quindi scoperto molto prima rispetto a un CSS file scaricato tramite una dichiarazione @import.

Il motivo è che, per far sì che una dichiarazione @import venga rilevato, il file CSS che lo contiene deve essere prima scaricato. Questo genera una cosiddetta catena di richieste che, nel caso dei CSS, ritarda il tempo necessario per la visualizzazione iniziale di una pagina. Un altro svantaggio è che i fogli di stile caricati utilizzando una dichiarazione @import non possono essere rilevati dal precaricano lo scanner e diventano risorse di blocco della visualizzazione scoperte in ritardo.

<!-- Do this instead: -->
<link rel="stylesheet" href="style.css">

Nella maggior parte dei casi puoi sostituire @import utilizzando un Elemento <link rel="stylesheet">. Gli elementi <link> consentono ai fogli di stile di essere scaricato contemporaneamente e riduce il tempo di caricamento complessivo, rispetto a @import che scarica i fogli di stile consecutivamente.

CSS critico incorporato

Il tempo necessario per scaricare i file CSS può aumentare il valore FCP di una pagina. Incorporato gli stili critici nel documento <head> eliminano la richiesta di rete per un CSS e, se eseguita correttamente, può migliorare i tempi di caricamento iniziali quando la cache del browser dell'utente non è preparata. Il CSS rimanente può essere caricato in modo asincrono o aggiunto alla fine dell'elemento <body>.

<head>
  <title>Page Title</title>
  <!-- ... -->
  <style>h1,h2{color:#000}h1{font-size:2em}h2{font-size:1.5em}</style>
</head>
<body>
  <!-- Other page markup... -->
  <link rel="stylesheet" href="non-critical.css">
</body>

Lo svantaggio di inserire una grande quantità di CSS comporta l'aggiunta di più byte alla Risposta HTML. Perché spesso le risorse HTML non possono essere memorizzate nella cache per molto tempo (o al tutti, ciò significa che il CSS incorporato non viene memorizzato nella cache per le pagine successive che potrebbero utilizzare lo stesso CSS nei fogli di stile esterni. Testa e misura il rendimento della tua pagina per assicurarti che i compromessi valgano l'impegno.

Demo CSS

JavaScript

JavaScript genera gran parte dell'interattività sul web, ma ha un costo. La spedizione di un codice JavaScript eccessivo può rallentare la risposta della pagina web durante la visualizzazione viene caricato e possono persino causare problemi di reattività che rallentano le interazioni. che possono essere frustranti per gli utenti.

JavaScript che blocca la visualizzazione

Quando carichi elementi <script> senza gli attributi defer o async, la classe il browser blocca l'analisi e il rendering finché lo script non viene scaricato, analizzato e eseguito. Analogamente, gli script in linea bloccano l'analizzatore sintattico finché lo script non viene analizzato ed eseguire il deployment.

async contro defer

async e defer consentono il caricamento degli script esterni senza bloccare il codice HTML mentre gli script (inclusi quelli incorporati) con type="module" differita automaticamente. Tuttavia, async e defer presentano alcune differenze che sono importanti da capire.

Una rappresentazione di vari meccanismi di caricamento degli script, tutti con dettagli sui ruoli di parser, recupero ed esecuzione in base ai vari attributi utilizzati, come asincrono, differito e type=&#39;module&#39; e una combinazione di tutti e tre.
. Informazioni fornite da https://html.spec.whatwg.org/multipage/scripting.html

Gli script caricati con async vengono analizzati ed eseguiti immediatamente dopo il download. mentre gli script caricati con defer vengono eseguiti quando è in corso l'analisi dei documenti HTML completato. Questo si verifica contemporaneamente all'evento DOMContentLoaded del browser. Inoltre, async script potrebbero essere eseguiti non nell'ordine corretto, mentre defer script potrebbero essere eseguiti vengono eseguite nell'ordine in cui appaiono nel markup.

Rendering lato client

In genere, dovresti evitare di usare JavaScript per eseguire il rendering di contenuti critici o di una l'elemento LCP della pagina. Questo è noto come rendering lato client ed è una tecnica ampiamente utilizzato nelle applicazioni a pagina singola (APS).

Il markup eseguito da JavaScript evita lo scanner di precaricamento, poiché le risorse contenuti nel markup visualizzato dal client non sono rilevabili dal markup. Questo potrebbe ritardare il download di risorse cruciali, come un'immagine LCP. Il browser inizia a scaricare l'immagine LCP solo dopo l'esecuzione dello script e l'aggiunta l'elemento al DOM. A sua volta, lo script può essere eseguito solo dopo rilevati, scaricati e analizzati. Questa procedura è nota come richiesta critica ed è da evitare.

Inoltre, è più probabile che il rendering di markup tramite JavaScript generi attività lunghe rispetto al markup scaricato dal server in risposta a una navigazione richiesta. L'uso intensivo del rendering lato client del codice HTML può influire negativamente latenza di interazione. Ciò è particolarmente vero nei casi in cui il DOM di una pagina molto grande, che attiva un notevole lavoro di rendering quando JavaScript modifica il DOM.

Minimizzazione

Come per i CSS, la minimizzazione di JavaScript riduce le dimensioni del file di una risorsa di script. Ciò può portare a download più rapidi, consentendo al browser di passare alla il processo di analisi e compilazione del codice JavaScript più rapidamente.

Inoltre, la minimizzazione di JavaScript va oltre la minimizzazione e altri asset, ad esempio il CSS. Quando JavaScript viene minimizzato, non viene solo rimosso. di elementi come spazi, tabulazioni e commenti, ma i simboli nella fonte JavaScript è abbreviato. Questo processo è a volte noto come uglificazione. A vedere la differenza, considera il seguente codice sorgente JavaScript:

// Unuglified JavaScript source code:
export function injectScript () {
  const scriptElement = document.createElement('script');
  scriptElement.src = '/js/scripts.js';
  scriptElement.type = 'module';

  document.body.appendChild(scriptElement);
}

Una volta uglificato il codice sorgente JavaScript precedente, il risultato potrebbe essere ad esempio il seguente snippet di codice:

// Uglified JavaScript production code:
export function injectScript(){const t=document.createElement("script");t.src="/js/scripts.js",t.type="module",document.body.appendChild(t)}

Nello snippet precedente, puoi vedere che la variabile leggibile scriptElement nella fonte è abbreviato in t. Se applicato su un modello grande raccolta di script, i risparmi possono essere notevoli, senza incidere le funzionalità fornite da JavaScript per la produzione di un sito web.

Se utilizzi un bundler per elaborare il codice sorgente del tuo sito web, viene spesso eseguita automaticamente per le build di produzione. Gli Uglifier, come Terser, ad esempio sono altamente configurabili, che consentono di modificare aggressività dell'algoritmo di uglificazione per ottenere il massimo risparmio. Tuttavia, i valori predefiniti per qualsiasi strumento di uglificazione sono in genere sufficienti per segnalare il giusto equilibrio tra dimensioni dell'output e conservazione delle capacità.

Demo JavaScript

Verifica le tue conoscenze

Qual è il modo migliore per caricare più file CSS nel browser?

La dichiarazione @import del CSS.
Riprova.
Più elementi <link>.
Esatto!

Che cosa fa lo scanner di precaricamento del browser?

È un parser HTML secondario che esamina il markup non elaborato per scoprire prima che l'analizzatore sintattico DOM possa individuarle prima.
Esatto!
Rileva <link rel="preload"> elemento in una risorsa HTML.
Riprova.

Perché il browser blocca temporaneamente l'analisi del codice HTML per impostazione predefinita quando scaricare risorse JavaScript?

Per evitare il flash di contenuti senza stile (FOUC).
Riprova.
Perché la valutazione di JavaScript è un'attività molto impegnativa della CPU e la messa in pausa L'analisi HTML fornisce alla CPU una maggiore larghezza di banda per completare il caricamento degli script.
Riprova.
Perché gli script possono modificare il DOM o accedervi in altro modo.
Esatto!

A seguire: assistenza al browser con hint delle risorse

Ora che hai un quadro del modo in cui le risorse caricate nell'elemento <head> possono influisce sul caricamento iniziale della pagina e su varie metriche, è il momento di andare avanti. Nei prossimi modulo, i nostri suggerimenti sulle risorse e scoprire in che modo possono fornire suggerimenti preziosi per il browser per iniziare a caricare le risorse e aprire connessioni multiorigine prima che il browser faccia altrimenti senza.