Ottimizza JavaScript di terze parti

Milica Mihajlija
Milica Mihajlija

Gli script di terze parti influiscono sul rendimento, perciò è importante controllarli regolarmente e utilizzare tecniche efficienti per il caricamento. Questo codelab mostra come ottimizzare il caricamento delle risorse di terze parti. Sono trattate le seguenti tecniche:

  • Rimandare il caricamento dello script

  • Caricamento lento delle risorse non critiche

  • Preconnessione alle origini richieste

L'app di esempio inclusa presenta una semplice pagina web con tre funzionalità provenienti da origini di terze parti:

  • Un video incorporato

  • Una libreria di visualizzazione dei dati per il rendering di un grafico a linee

  • Un widget di condivisione sui social media

Screenshot della pagina con le risorse di terze parti evidenziate.
Risorse di terze parti nell'app di esempio.

Inizierai misurando il rendimento dell'app e poi applichi ogni tecnica per migliorare diversi aspetti del rendimento dell'app.

Misurare le prestazioni

Innanzitutto, apri l'app di esempio nella visualizzazione a schermo intero:

  1. Fai clic su Remix per modificare per rendere il progetto modificabile.
  2. Per visualizzare l'anteprima del sito, premi Visualizza app, quindi premi A schermo intero schermo intero.

Esegui un controllo del rendimento di Lighthouse sulla pagina per stabilire il rendimento di riferimento:

  1. Premi "Control+Maiusc+J" (o "Comando+Opzione+J" su Mac) per aprire DevTools.
  2. Fai clic sulla scheda Lighthouse.
  3. Fai clic su Dispositivo mobile.
  4. Seleziona la casella di controllo Prestazioni. Puoi deselezionare le altre caselle di controllo nella sezione Controlli.
  5. Fai clic su 3G veloce simulato, rallentamento CPU 4x.
  6. Seleziona la casella di controllo Libera spazio di archiviazione.
  7. Fai clic su Esegui controlli.

Quando esegui un controllo sul tuo computer, i risultati esatti possono variare, ma dovresti notare che il tempo di First Contentful Paint (FCP) è piuttosto elevato e che Lighthouse suggerisce due opportunità di indagine: Elimina le risorse che bloccano il rendering e Esegui la preconnessione alle origini richieste. Anche se tutte le metriche sono verdi, le ottimizzazioni produrranno comunque miglioramenti.

Screenshot del controllo Lighthouse che mostra un tempo FCP di 2,4 secondi e due opportunità: elimina le risorse che bloccano il rendering e esegui il precollegamento alle origini richieste.

Rimandare JavaScript di terze parti

Il controllo Elimina le risorse che bloccano il rendering ha rilevato che puoi risparmiare tempo posticipando uno script proveniente da d3js.org:

Screenshot del controllo Elimina le risorse di blocco della visualizzazione con lo script d3.v3.min.js evidenziato.

D3.js è una libreria JavaScript per la creazione di visualizzazioni dei dati. Il file script.js nell'app di esempio utilizza le funzioni di utilità D3 per creare il grafico a linee SVG e aggiungerlo alla pagina. L'ordine delle operazioni è importante: script.js deve essere eseguito dopo l'analisi del documento e il caricamento della libreria D3, motivo per cui è incluso subito prima del tag di chiusura </body> in index.html.

Tuttavia, lo script D3 è incluso nel <head> della pagina, il che blocca l'analisi del resto del documento:

Screenshot di index.html con il tag script evidenziato nell&#39;intestazione.

Due attributi magici possono sbloccare il parser se vengono aggiunti al tag script:

  • async garantisce che gli script vengano scaricati in background ed eseguiti alla prima occasione al termine del download.

  • defer garantisce che i download degli script avvengano in background e che vengano eseguiti dopo il completamento dell'analisi.

Poiché questo grafico non è molto importante per la pagina complessiva e molto probabilmente sarà sotto la piega, utilizza defer per assicurarti che non ci siano blocchi del parser.

Passaggio 1: carica lo script in modo asincrono con l'attributo defer

Nella riga 17 in index.html, aggiungi l'attributo defer all'elemento <script>:

<script src="https://d3js.org/d3.v3.min.js" defer></script>

Passaggio 2: assicurati che l'ordine delle operazioni sia corretto

Ora che D3 è differito, script.js verrà eseguito prima che D3 sia pronto, generando un errore.

Gli script con l'attributo defer vengono eseguiti nell'ordine in cui sono stati specificati. Per assicurarti che script.js venga eseguito dopo che D3 è pronto, aggiungi defer e spostalo fino al <head> del documento, subito dopo l'elemento <script> di D3. Ora non blocca più l'analizzatore e il download inizia prima.

<script src="https://d3js.org/d3.v3.min.js" defer></script>
<script src="./script.js" defer></script>

Carica risorse di terze parti tramite caricamento lento

Tutte le risorse che si trovano below the fold sono ottime candidate per il caricamento lento.

L'app di esempio ha un video di YouTube incorporato in un iframe. Per controllare quante richieste vengono inviate dalla pagina e quali provengono dall'iframe di YouTube incorporato:

  1. Per visualizzare l'anteprima del sito, premi Visualizza app, quindi premi A schermo intero schermo intero.
  2. Premi "Control+Maiusc+J" (o "Comando+Opzione+J" su Mac) per aprire DevTools.
  3. Fai clic sulla scheda Rete.
  4. Seleziona la casella di controllo Disattiva cache.
  5. Seleziona 3G veloce nel menu a discesa Ritardo.
  6. Ricarica la pagina.

Screenshot del riquadro Rete di DevTools.

Il riquadro Rete indica che la pagina ha effettuato un totale di 28 richieste e ha trasferito quasi 1 MB di risorse compresse.

Per identificare le richieste effettuate da iframe di YouTube, cerca l'ID video 6lfaiXM6waw nella colonna Autore. Per raggruppare tutte le richieste per dominio:

  • Nel riquadro Rete, fai clic con il tasto destro del mouse sul titolo di una colonna.

  • Nel menu a discesa, seleziona la colonna Domains (Domini).

  • Per ordinare le richieste per dominio, fai clic sul titolo della colonna Domains (Domini).

Il nuovo ordinamento rivela che ci sono richieste aggiuntive ai domini Google. In totale, l'iframe di YouTube effettua 14 richieste per script, fogli di stile, immagini e caratteri. Tuttavia, a meno che gli utenti non spostino lo scorrimento verso il basso per riprodurre il video, non hanno davvero bisogno di tutte queste risorse.

Se aspetti di caricare il video tramite il caricamento differito finché un utente non scorre fino a quella sezione della pagina, riduci il numero di richieste effettuate inizialmente dalla pagina. Questo approccio consente di salvare i dati degli utenti e di velocizzare il caricamento iniziale.

Un modo per implementare il caricamento lazy è utilizzare Intersection Observer, un'API del browser che ti avvisa quando un elemento entra o esce dall'area visibile del browser.

Passaggio 1: impedisci il caricamento iniziale del video

Per eseguire il caricamento differito dell'iframe del video, devi prima impedire il caricamento nel modo consueto. A tal fine, sostituisci l'attributo src con l'attributo data-src per specificare l'URL del video:

<iframe width="560" height="315" data-src="https://www.youtube.com/embed/lS9D6w1GzGY" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

data-src è un attributo dati che ti consente di memorizzare informazioni aggiuntive sugli elementi HTML standard. Un attributo dati può avere qualsiasi nome, purché inizi con "data-".

Un iframe senza src non viene caricato.

Passaggio 2: utilizza Intersection Observer per il caricamento differito del video

Per caricare il video quando un utente arriva a quel punto, devi sapere quando ciò accade. È qui che entra in gioco l'API Intersection Observer. L'API Intersection Observer ti consente di registrare una funzione di callback che viene eseguita ogni volta che un elemento che vuoi monitorare entra o esce dall'area visibile.

Per iniziare, crea un nuovo file e assegnagli il nome lazy-load.js:

  • Fai clic su Nuovo file e assegna un nome al file.
  • Fai clic su Aggiungi questo file.

Aggiungi il tag script all'intestazione del documento:

 <script src="/lazy-load.js" defer></script>

In lazy-load.js, crea un nuovo IntersectionObserver e passagli una funzione di callback da eseguire:

// create a new Intersection Observer
let observer = new IntersectionObserver(callback);

Ora indica a observer un elemento target da guardare (in questo caso l'iframe del video) passandolo come argomento nel metodo observe:

// the element that you want to watch
const element = document.querySelector('iframe');

// register the element with the observe method
observer.observe(element);

callback riceve un elenco di oggetti IntersectionObserverEntry e l'oggetto IntersectionObserver stesso. Ogni voce contiene un elemento target e proprietà che descrivono le sue dimensioni, la sua posizione, il momento in cui è entrato nel viewport e altro ancora. Una delle proprietà di IntersectionObserverEntry è isIntersecting, un valore booleano uguale a true quando l'elemento entra nell'area visibile.

In questo esempio, target è iframe. isIntersecting è uguale a true quando target entra nell'area visibile. Per vedere come funziona, sostituisci callback con la seguente funzione:

let observer = new IntersectionObserver(callback);
let observer = new IntersectionObserver(function(entries, observer) {
    entries.forEach(entry => {
      console.log(entry.target);
      console.log(entry.isIntersecting);
    });
  });
  1. Per visualizzare l'anteprima del sito, premi Visualizza app, quindi premi A schermo intero schermo intero.
  2. Premi "Control+Maiusc+J" (o "Comando+Opzione+J" su Mac) per aprire DevTools.
  3. Fai clic sulla scheda Console.

Prova a scorrere verso l'alto e verso il basso. Dovresti vedere il valore di isIntersecting cambiare e l'elemento target registrato nella console.

Per caricare il video quando l'utente scorre fino alla sua posizione, utilizza isIntersecting come condizione per eseguire una funzione loadElement, che recupera il valore da data-src dell'elemento iframe e lo imposta come attributo src dell'elemento iframe. Questa sostituzione attiva il caricamento del video. Una volta caricato il video, chiama il metodo unobserve su observer per interrompere la visione dell'elemento target:

let observer = new IntersectionObserver(function (entries, observer) {
  entries.forEach(entry => {
    console.log(entry.target);
    console.log(entry.isIntersecting);
  });
});
    if (entry.isIntersecting) {
      // do this when the element enters the viewport
      loadElement(entry.target);
      // stop watching
      observer.unobserve(entry.target);
    }
  });
});

function loadElement(element) {
  const src = element.getAttribute('data-src');
  element.src = src;
}

Passaggio 3: rivaluta il rendimento

Per vedere come sono cambiate le dimensioni e il numero di risorse, apri il riquadro Rete di DevTools e ricarica di nuovo la pagina. Il riquadro Rete indica che la pagina ha effettuato 14 richieste e solo 260 KB. È un miglioramento significativo.

Ora scorri verso il basso nella pagina e tieni d'occhio il riquadro Rete. Quando arrivi al video, dovresti vedere che la pagina attiva richieste aggiuntive.

Preconnettiti alle origini richieste

Hai posticipato il codice JavaScript non critico e hai caricato le richieste di YouTube in modo lazy, quindi è arrivato il momento di ottimizzare i restanti contenuti di terze parti.

L'aggiunta dell'attributo rel=preconnect a un link indica al browser di stabilire una connessione a un dominio prima che venga effettuata la richiesta della risorsa. Questo attributo è ideale per le origini che forniscono le risorse di cui hai la certezza che la pagina abbia bisogno.

Il controllo Lighthouse eseguito nel primo passaggio suggerito in Eseguire la preconnessione alle origini richieste indica che puoi risparmiare circa 400 ms stabilendo connessioni anticipate a staticxx.facebook.com e youtube.com:

Controllo Precollega alle origini richieste con il dominio staticxx.facebook.com evidenziato.

Poiché il video di YouTube ora viene caricato in modo lazy, rimane solo staticxx.facebook.com, la sorgente del widget di condivisione sui social media. Per stabilire una connessione anticipata a questo dominio, è sufficiente aggiungere un tag <link> al <head> del documento:

  <link rel="preconnect" href="https://staticxx.facebook.com">

Rivalutare il rendimento

Ecco lo stato della pagina dopo l'ottimizzazione. Segui i passaggi descritti nella sezione Misurare il rendimento del codelab per eseguire un altro audit Lighthouse.

Audit Lighthouse che mostra un FCP di 1 secondo e un punteggio di prestazioni pari a 99.