Incorporamento di risorse nei framework JavaScript

Miglioramento di Largest Contentful Paint nell'ecosistema JavaScript.

Nell'ambito del progetto Aurora, Google collabora con i framework web più diffusi per assicurarsi che funzionino bene in base a Core Web Vitals. Angular e Next.js supportano già l'inserimento in linea dei caratteri, come spiegato nella prima parte di questo articolo. La seconda ottimizzazione che tratteremo riguarda l'incorporamento di CSS critici, che ora è abilitato per impostazione predefinita nell'interfaccia a riga di comando Angular e ha un'implementazione ancora in corso in Nuxt.js.

Inserimento in linea dei caratteri

Dopo aver analizzato centinaia di applicazioni, il team di Aurora ha scoperto che gli sviluppatori spesso includono i caratteri nelle loro applicazioni facendovi riferimento nell'elemento <head> di index.html. Ecco un esempio di come apparirà quando includi le icone Material:

<!doctype html>
<html lang="en">
<head>
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
  ...
</html>

Anche se questo pattern è completamente valido e funzionale, blocca il rendering dell'applicazione e introduce una richiesta aggiuntiva. Per comprendere meglio cosa sta succedendo, dai un'occhiata al codice fonte del foglio di stile a cui si fa riferimento nel codice HTML riportato sopra:

/* fallback */
@font-face {
  font-family: 'Material Icons';
  font-style: normal;
  font-weight: 400;
  src: url(https://fonts.gstatic.com/font.woff2) format('woff2');
}

.material-icons {
  /*...*/
}

Tieni presente che la definizione di font-face fa riferimento a un file esterno ospitato su fonts.gstatic.com. Durante il caricamento dell'applicazione, il browser deve prima scaricare il foglio di stile originale a cui viene fatto riferimento nell'intestazione.

Un&#39;immagine che mostra come il sito web deve inviare una richiesta al server e scaricare il foglio di stile esterno
Innanzitutto, il sito web carica il foglio di stile dei caratteri.

Successivamente, il browser scarica il file woff2 e infine può procedere con il rendering dell'applicazione.

Un&#39;immagine che mostra le due richieste effettuate, una per il foglio di stile dei caratteri e la seconda per il file del carattere.
Successivamente, viene inviata una richiesta di caricamento del carattere.

Un'opportunità di ottimizzazione è scaricare il foglio di stile iniziale in fase di compilazione e inserirlo in linea in index.html. In questo modo, viene saltato un intero viaggio di andata e ritorno alla CDN in fase di esecuzione, riducendo il tempo di blocco.

Quando si crea l'applicazione, viene inviata una richiesta alla rete CDN, che recupera il foglio di stile e lo incorpora nel file HTML, aggiungendo <link rel=preconnect> al dominio. Se applichiamo questa tecnica, otteniamo il seguente risultato:

<!doctype html>
<html lang="en">
<head>
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin >
  <style type="text/css">
  @font-face{font-family:'Material Icons';font-style:normal;font-weight:400;src:url(https://fonts.gstatic.com/font.woff2) format('woff2');}.material-icons{/*...*/}</style>
  ...
</html>

Il carattere incorporato è ora disponibile in Next.js e Angular

Quando gli sviluppatori di framework implementano l'ottimizzazione negli strumenti sottostanti, facilitano l'abilitazione delle applicazioni nuove ed esistenti, portando il miglioramento all'intero ecosistema.

Questo miglioramento è attivato per impostazione predefinita a partire da Next.js 10.2 e Angular 11. Entrambi supportano l'inserimento in linea dei caratteri Google e Adobe. Angular prevede di introdurre quest'ultima nella versione 12.2.

Puoi trovare l'implementazione del fonte incorporato in Next.js su GitHub e guardare il video che spiega questa ottimizzazione nel contesto di Angular.

Incorporazione del CSS critico

Un altro miglioramento prevede il miglioramento delle metriche First Contentful Paint (FCP) e Largest Contentful Paint (LCP) inserendo in linea il CSS critico. Il CSS fondamentale di una pagina include tutti gli stili usati al rendering iniziale. Per scoprire di più sull'argomento, consulta Rimandare il CSS non critico.

Abbiamo notato che molte applicazioni caricano gli stili in modo sincrono, il che blocca il rendering dell'applicazione. Una soluzione rapida è caricare gli stili in modo asincrono. Anziché caricare gli script con media="all", imposta il valore dell'attributo media su print e, al termine del caricamento, sostituire il valore dell'attributo con all:

<link rel="stylesheet" href="..." media="print" onload="this.media='all'">

Tuttavia, questa pratica può causare lo sfarfallio dei contenuti non formattati.

La pagina sembra sfarfallare durante il caricamento degli stili.

Il video qui sopra mostra il rendering di una pagina, che carica i relativi stili in modo asincrono. Lo sfarfallio si verifica perché il browser inizia prima a scaricare gli stili, poi esegue il rendering dell'HTML che segue. Una volta scaricati gli stili, il browser attiva l'evento onload dell'elemento link, aggiorna l'attributo media su all e applica gli stili al DOM.

Durante il tempo che intercorre tra il rendering dell'HTML e l'applicazione degli stili, la pagina è parzialmente senza stile. Quando il browser utilizza gli stili, si nota lo sfarfallio, un'esperienza utente negativa e una regressione in Cumulative Layout Shift (CLS).

L'incorporazione di CSS critici, insieme al caricamento asincrono degli stili, può migliorare il comportamento di caricamento. Lo strumento Critters individua gli stili utilizzati nella pagina esaminando i selettori in un foglio di stile e confrontandoli con il codice HTML. Quando trova una corrispondenza, considera gli stili corrispondenti come parte del CSS fondamentale e li incorpora.

Ad esempio:

Cosa non fare
<head>
   <link rel="stylesheet" href="/styles.css" media="print" onload="this.media='all'">
</head>
<body>
  <section>
    <button class="primary"></button>
  </section>
</body>
/* styles.css */
section button.primary {
  /* ... */
}
.list {
  /* ... */
}

Esempio prima dell'inserimento in linea.

Nell'esempio riportato sopra, i Critters leggono e analizzano i contenuti di styles.css, poi abbinano i due selettori all'HTML e scoprono che utilizziamo section button.primary. Infine, i critters inseriranno gli stili corrispondenti in linea nel <head> della pagina, ottenendo:

Cosa fare
<head>
  <link rel="stylesheet" href="/styles.css" media="print" onload="this.media='all'">
  <style>
  section button.primary {
    /* ... */
  }
  </style>
</head>
<body>
  <section>
    <button class="primary"></button>
  </section>
</body>

Esempio dopo l'incorporamento.

Dopo aver inserito in linea il CSS critico nel codice HTML, noterai che il tremolio della pagina non è più presente:

Il caricamento della pagina dopo l'inserimento in linea del CSS.

L'incorporamento CSS critico è ora disponibile in Angular e abilitato per impostazione predefinita nella versione 12. Se utilizzi la versione 11, attivala impostando la proprietà inlineCritical su true in angular.json. Per attivare questa funzionalità in Next.js, aggiungi experimental: { optimizeCss: true } a next.config.js.

Conclusioni

In questo post abbiamo accennato ad alcuni aspetti della collaborazione tra Chrome e i framework web. Se sei un autore di framework e riconosci alcuni dei problemi che abbiamo affrontato nella tua tecnologia, ci auguriamo che i nostri risultati ti incentivino ad applicare ottimizzazioni del rendimento simili.

Scopri di più sui miglioramenti. Puoi trovare un elenco completo del lavoro di ottimizzazione che abbiamo svolto per Core Web Vitals nel post Introduzione ad Aurora.