Ottimizzare la Priorità di JavaScript per Caricamenti di Pagina più Veloci

Scopri come assegnare efficacemente la priorità agli script per migliorare i Core Web Vitals.

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2024-12-12

Gestione delle Priorità di JavaScript per Migliori Prestazioni Web

Una cosa è sempre stata chiara: non tutti i JavaScript sono uguali. Alcuni script gestiscono interazioni critiche come 'interazione con il menu' o 'aggiungi al carrello' mentre altri script sono molto meno importanti. Prendiamo ad esempio lo script popup 'exit intent' che invita i visitatori che stanno per lasciare il sito a compilare un questionario. Sono sicuro che potremmo tutti fare a meno degli ultimi, ma sarebbe davvero difficile navigare un sito web senza i primi.

Eppure, nel  'sito web medio' a livello tecnico questa distinzione non viene quasi mai fatta. Tutti i JavaScript vengono 'semplicemente aggiunti' alla pagina e al browser viene lasciato il compito di gestirli. Questo è un problema perché il browser non ha idea di cosa sia importante e cosa no. Noi, come sviluppatori, lo sappiamo. Quindi risolviamolo!

Come la priorità di JavaScript può influenzare i Core Web Vitals

Aggiungere semplicemente script alla pagina senza la giusta considerazione può influenzare tutti e 3 i Core Web Vitals. Il Largest Contentful Paint, l 'Interaction to Next Paint e il Cumulative Layout Shift. 

javascript lcp impact example

Esempio: la risorsa di rete LCP viene ritardata da JavaScript che bloccano il rendering

Il Largest Contentful Paint è soggetto alla competizione per banda e CPU. Quando troppi script competono per le risorse di rete iniziali, la risorsa di rete del Largest Contentful Paint viene ritardata e il lavoro iniziale della CPU ritarderà l'LCP bloccando il main thread.

L'Interaction to Next Paint può essere influenzato da script eseguiti subito prima di un'interazione. Quando gli script vengono eseguiti, bloccano il main thread e ritardano qualsiasi interazione durante quel tempo di esecuzione.

Gli script possono anche causare un Cumulative Layout Shift se gli script 'modificano l'aspetto della pagina'. Gli script pubblicitari che iniettano banner nella pagina e gli slider sono noti per questo.

5 Tipi di priorità JavaScript

Mi piace distinguere tra 5 tipi di priorità JavaScript. Discutiamoli brevemente prima di approfondire.

  • Render Critical: questi script sono tra i peggiori da avere. Modificano il layout della pagina e senza caricare questi script il layout sarà completamente diverso. Esempio: alcuni script per slider o un A/B test.
  • Script Critici: Questi script gestiscono funzionalità critiche della pagina e senza di essi attività critiche come aggiungere un prodotto al carrello, la ricerca nel sito o la navigazione non sono possibili.
  • Script Importanti. Questi script gestiscono logiche (di business) importanti e il sito dipende da essi. Ad esempio: Analytics
  • Script Opzionali. Questi script sono utili ma se necessario non sono realmente indispensabili per il funzionamento della pagina. Ad esempio un widget di chat o un exit intent
  • Script Futuri. Questi script potrebbero essere critici o opzionali ma non ne abbiamo bisogno adesso perché 'altri passaggi' devono essere completati prima di poter effettivamente utilizzare questi script. Ad esempio uno script per il checkout multi-step.
Ora che abbiamo un'idea delle priorità degli script, analizziamole nel dettaglio!

1. Script Render-Critical

Questi sono gli script più impattanti, poiché influenzano direttamente come la pagina viene visualizzata. Senza di essi, il layout potrebbe rompersi o apparire drasticamente diverso dal design previsto. Esempi includono script per slider o framework di A/B testing che alterano il layout nelle prime fasi del caricamento. 

Il problema con questo tipo di script è che non possono essere differiti o ritardati. Qualsiasi ritardo causerà lo spostamento del layout del sito web, provocando una scarsa UX e il fallimento dei Core Web Vitals.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Page Title</title>
    <link href="styles.css" rel="stylesheet" />
    <script src="render-critical.js"></script>
  </head>
  <body></body>
</html>

Best Practice:

  • Evitate gli script render critical come questi quando possibile. Riscrivete il codice per evitare la dipendenza da questo tipo di script.
  • Se non c'è alternativa, inserite inline o caricate solo le parti assolutamente necessarie di questi script. 
  • Non utilizzate defer o async per questi script e posizionateli nella parte superiore dell'head per attivare un download 'il prima possibile'.

2. Script Critici

Questi script abilitano interazioni fondamentali. Senza di essi, attività critiche come la navigazione del sito, l'aggiunta di articoli al carrello, l'avviso sui cookie o l'esecuzione di una ricerca diventano impossibili. Sono indispensabili per le funzionalità principali del sito.

Questi script dovrebbero essere posizionati nell'head della pagina con l'attributo async o defer.

<script defer src="critical.js"></script>
<script async src="critical.js"></script>

Best Practice:

  • Mantenete al minimo script come questi e non combinate questa funzionalità con altre funzionalità meno critiche.
  • Caricate questi script in anticipo usando async o defer, a seconda delle loro dipendenze.
  • Utilizzate strumenti di Real User Monitoring (RUM), come CoreDash, per identificare colli di bottiglia nell'esecuzione e assicurarvi che le loro prestazioni siano allineate alle esigenze degli utenti.

3. Script Importanti

Pur non essendo direttamente legati all'usabilità del sito, gli script importanti supportano funzioni chiave del business. Gli script di Analytics, ad esempio, forniscono dati essenziali ma non devono caricarsi prima degli elementi visivi più importanti. Ovviamente la distinzione tra script critici e importanti può essere oggetto di dibattito, quindi assicuratevi di parlare con tutti gli stakeholder prima di impostare questa priorità!

Ci sono 3 modi per abbassare la priorità degli script per questo tipo di script.

<html>
<head>
<!-- method 1: low fetchpriority -->
<script fetchpriority="low" defer src="important.js"></script>

<!-- method 2: inject after DOMContentLoaded -->
<script>
  document.addEventListener('DOMContentLoaded', function() {
    var script = document.createElement('script');
    script.src = 'important.js';
    document.body.appendChild(script);
  });
</script>
</head>
<body>

<!-- method 3: place at the bottom of the page -->
<script defer src="important.js"></script>
</body>
</html>

1. Low fetchpriority. 

Impostare la fetchpriority abbasserà la priorità relativa dello script. Altri script differiti o asincroni verranno probabilmente accodati con una priorità alta mentre gli script con fetchpriority="low" verranno accodati con una priorità bassa. A seconda della vostra pagina (o del vostro rendering path) questo potrebbe essere sufficiente per dare priorità ad altre risorse come la vostra immagine Largest Contentful Paint e i font importanti. 

2: Iniezione dopo DOMContentLoaded

Iniettando lo script dopo l'evento DOMContentLoaded, vi assicurate che lo script inizi a scaricarsi subito dopo che l'HTML è stato completamente analizzato. Questo permette alle risorse scopribili, come immagini e font, di avere la precedenza. Questo metodo offre un equilibrio: lo script inizia a caricarsi abbastanza presto da evitare ritardi nelle funzionalità ma non compete con le risorse iniziali cruciali per il rendering iniziale della pagina.

3: Posizionamento in fondo alla pagina

Questa tecnica classica differisce il caricamento dello script fino a dopo che il browser ha elaborato l'intero documento e raggiunge più o meno lo stesso risultato della tecnica precedente. L'unica differenza è che la tecnica 2 bypassa il preload scanner del browser mentre questa tecnica no.  Il preload scanner è uno scanner rapido e leggero che il browser utilizza per identificare e accodare velocemente le risorse critiche. Bypassare il preload scanner potrebbe essere una buona idea se c'è la possibilità di immagini lazy loaded nel viewport, mentre utilizzare il preload scanner accelererà il caricamento di questo script.

4. Script Opzionali

Questi script migliorano la user experience ma non sono necessari per il funzionamento del sito. Esempi includono widget di chat, popup per feedback dei clienti o animazioni opzionali. Sebbene utili, non dovrebbero interferire con la user experience principale.

Questi script sono candidati ideali per il caricamento con un pattern chiamato 'lazy on load'. Questo significa attendere l'evento load della pagina e poi, durante il tempo di inattività, iniettare lo script.  Attendere l'evento load assicura che lo script non competa per banda e CPU  con risorse iniziali più importanti. Attendere un momento di inattività assicura che il browser non stia gestendo attività più importanti come l'input dell'utente.

Ecco un esempio funzionante:

window.addEventListener("load", () => {
  window.requestIdleCallback(() => {
    const script = document.createElement("script");
    script.src = "/path/to/script.js";
    document.head.appendChild(script);
  });
});

Best Practice:

  • Caricate questi script in modo lazy dopo che la pagina è stata caricata e attendete un momento di inattività.
  • Tenete presente che gli script caricati con questo pattern non hanno la garanzia di caricarsi velocemente

5. Script Futuri

Gli script futuri sono quelli che non saranno necessari fino a quando non saranno soddisfatte condizioni specifiche. Ad esempio, uno script per il checkout multi-step diventa rilevante solo dopo che un utente ha aggiunto articoli al carrello. Questi script possono spesso attendere molto più avanti nel percorso dell'utente.

Date un'occhiata a questo esempio. Utilizza l'intersection observer per caricare la logica JS necessaria per lo script di registrazione solo quando il form è nel viewport visibile.

<!DOCTYPE html>
<html>
  <head>
    <script>
      document.addEventListener("DOMContentLoaded", function () {
        const form = document.querySelector("form");
        const observer = new IntersectionObserver(function (entries) {
          entries.forEach((entry) => {
            if (entry.isIntersecting) {
              const script = document.createElement("script");
              script.src = "/sign-up.js";
              document.head.appendChild(script);
              observer.unobserve(form);
            }
          });
        });
        observer.observe(form);
      });
    </script>
  </head>
  <body>
    <form action="/sign-up" method="post">
      <label for="email">Email:</label>
      <input type="email" id="email" name="email" required />
      <button type="submit">Sign Up</button>
    </form>
  </body>
</html>

Best Practice:

  • Caricate questi script on demand, attivati dalle azioni dell'utente.
  • Utilizzate tecniche di code-splitting per distribuire solo le parti necessarie in ogni passaggio.
  • Iniettate dinamicamente questi script solo quando necessario, ad esempio quando un utente scorre fino a una sezione specifica.

Urgent Fix Required?

Google Search Console failing? I offer rapid-response auditing to identify the failure point within 48 hours.

Request Urgent Audit >>

  • 48hr Turnaround
  • Rapid Response
  • Failure Identification
Ottimizzare la Priorità di JavaScript per Caricamenti di Pagina più VelociCore Web Vitals Ottimizzare la Priorità di JavaScript per Caricamenti di Pagina più Veloci