16 metodi per differire o programmare JavaScript

Impara come differire e programmare JavaScript

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2026-02-24

Perché differire o programmare JavaScript?

JavaScript può rallentare (e lo farà) il tuo sito web in vari modi. Questo può avere ogni sorta di impatto negativo sui Core Web Vitals. JavaScript può competere per le risorse di rete, può competere per le risorse della CPU (bloccare il thread principale) e può persino bloccare l'analisi di una pagina web. Differire e programmare i tuoi script può migliorare drasticamente i Core Web Vitals.

Ultima revisione di Arjen Karel a febbraio 2026

Per ridurre al minimo i brutti effetti che JavaScript può avere sui Core Web Vitals, di solito è una buona idea specificare quando uno script viene messo in coda per il download e programmare quando può occupare tempo di CPU e bloccare il thread principale.

Come può il tempismo di JavaScript influenzare i Core Web Vitals?

Come può il tempismo di JavaScript influenzare i Core Web Vitals? Dai un'occhiata a questo esempio reale. La prima pagina viene caricata con JavaScript 'render blocking'.  Le metriche di pittura così come il Total Blocking Time sono piuttosto pessime. Il secondo esempio riguarda esattamente la stessa pagina ma con il JavaScript differito. Vedrai che l'immagine LCP ha comunque subito un duro colpo. Il terzo esempio ha lo stesso script eseguito dopo l'evento 'load' della pagina e ha le chiamate di funzione suddivise in parti più piccole. Quest'ultimo passa i Core Web Vitals con margine.

js render blocking lhnull
js deferred lhnull
js after load lhnull


Per impostazione predefinita, i file JavaScript esterni nell'head della pagina bloccheranno la creazione dell'albero di rendering. Più specificamente: quando il browser incontra uno script nel documento, deve mettere in pausa la costruzione del DOM, passare il controllo al runtime JavaScript e lasciare che lo script venga eseguito prima di procedere con la costruzione del DOM. Questo influenzerà le tue Paint Metrics (Largest Contentful Paint e First Contentful Paint).

I JavaScript differiti o async possono comunque influire sulle metriche di pittura, specialmente il Largest Contentful Paint perché verranno eseguiti, e bloccheranno il thread principale, una volta che il DOM è stato creato (e gli elementi LCP comuni come le immagini potrebbero non essere stati scaricati).

I file JavaScript esterni competeranno anche per le risorse di rete. I file JavaScript esterni di solito vengono scaricati prima delle immagini. Se stai scaricando troppi script, il download delle tue immagini subirà un ritardo.

Infine, ma non meno importante, JavaScript potrebbe bloccare o ritardare l'interazione dell'utente. Quando uno script utilizza le risorse della CPU (bloccando il thread principale), un browser non risponderà all'input (clic, scorrimento, ecc.) fino a quando quello script non sarà stato completato. Questo influisce direttamente sul tuo punteggio di Interaction to Next Paint (INP).

L'impatto è misurabile. Secondo il Web Almanac 2025, solo il 15% delle pagine mobile supera l'audit delle render-blocking resources. Il Total Blocking Time mediano su mobile è di 1.916 millisecondi. Sono quasi 2 secondi interi in cui il browser non può rispondere all'input dell'utente. Scegliere il giusto metodo di deferimento per ogni script è il modo per abbassare quel numero.

Come fa la programmazione o il differimento di JavaScript a risolvere i Core Web Vitals?

La programmazione o il differimento di JavaScript non risolve i Core Web Vitals di per sé. Si tratta di usare lo strumento giusto per la situazione giusta. Come regola, dovresti cercare di ritardare i tuoi script il meno possibile, ma metterli in coda per il download ed eseguirli al momento opportuno.

Come scegliere il giusto metodo di deferimento?

Non tutti gli script sono uguali e ogni script ha la propria funzionalità. Alcuni script sono importanti da avere all'inizio del processo di rendering, altri no.

js defer vs async vs blockingnull

Mi piace categorizzare i JavaScript in 4 gruppi in base al loro livello di importanza.

1. Render critical. Questi sono gli script che cambieranno l'aspetto di una pagina web. Se non si caricano, la pagina non sembrerà completa. Questi script dovrebbero essere evitati a tutti i costi. Se non puoi evitarli per qualche motivo, non dovrebbero essere differiti. Ad esempio uno slider in alto o uno script di A/B testing.
2. Critical. Questi script non cambieranno l'aspetto di una pagina web (troppo), ma la pagina non funzionerà bene senza di essi. Questi script dovrebbero essere differiti o async. Ad esempio i tuoi script per il menu.
3. Important. Questi sono gli script che vuoi caricare perché sono preziosi per te o per il visitatore. Tendo a caricare questi script dopo che l'evento load è stato attivato. Ad esempio analytics o un pulsante 'torna su'.
4. Nice to have. Questi sono script di cui puoi fare a meno se ne hai assolutamente bisogno. Carico questi script con la priorità più bassa e li eseguo solo quando il browser è inattivo. Ad esempio un widget di chat o un pulsante Facebook.

Metodo 1: Usa l'attributo defer

Gli script con l'attributo defer verranno scaricati in parallelo e vengono aggiunti alla coda JavaScript defer. Subito prima che il browser attivi l'evento DOMContentLoaded, tutti gli script in quella coda verranno eseguiti nell'ordine in cui appaiono nel documento.

<script  src='javascript.js'></script>

Il 'trucco defer' di solito risolve molti problemi, specialmente le paint metrics. Sfortunatamente non c'è alcuna garanzia, dipende dalla qualità degli script. Gli script differiti verranno eseguiti una volta che tutti gli script sono stati caricati e l'HTML è stato analizzato (DOMContentLoaded). L'elemento LCP (di solito un'immagine grande) potrebbe non essere caricato entro quel momento e gli script differiti causeranno comunque un ritardo nel LCP.

Quando usarlo:

Usa gli script differiti per gli script Critical che sono necessari il prima possibile.

Vantaggi:

  1. Gli script differiti verranno scaricati in parallelo
  2. Il DOM sarà disponibile al momento dell'esecuzione

Svantaggi:

  1. Gli script differiti potrebbero ritardare le tue metriche LCP 
  2. Gli script differiti bloccheranno il thread principale una volta eseguiti
  3. Potrebbe non essere sicuro differire gli script quando gli script inline o async dipendono da essi

Metodo 2: Usa l'attributo async

Gli script con l'attributo async si scaricano in parallelo e verranno eseguiti immediatamente dopo aver terminato il download.

<script  src='javascript.js'></script>

Gli script async faranno poco per risolvere i problemi di pagespeed. È fantastico che vengano scaricati in parallelo, ma questo è tutto. Una volta scaricati bloccheranno il thread principale non appena verranno eseguiti.

Quando usarlo:

Usa gli script async per gli script Critical che sono necessari il prima possibile e sono autonomi (non dipendono da altri script).

Vantaggi:

  1. Gli script async verranno scaricati in parallelo.
  2. Gli script async verranno eseguiti il prima possibile.

Svantaggi:

  1. DOMContentLoaded potrebbe verificarsi sia prima che dopo async.
  2. L'ordine di esecuzione degli script sarà sconosciuto in anticipo.
  3. Non puoi usare script async che si basano su altri script async o differiti

Per un confronto dettagliato di questi due approcci, vedi defer vs async e come questo influisce sui Core Web Vitals.

Metodo 3: Usa i moduli

Gli script modulari sono differiti per impostazione predefinita a meno che non abbiano l'attributo async. In quel caso verranno trattati come script async

<script  src='javascript.js'></script>

I moduli sono un nuovo modo di pensare a JavaScript e risolvono alcuni difetti di progettazione. A parte questo, l'uso dei moduli script non accelererà il tuo sito web. 

Quando usarli:

Quando la tua applicazione è costruita in modo modulare ha senso utilizzare anche i moduli JavaScript.

Vantaggi:

  1. I moduli sono differiti per impostazione predefinita
  2. I moduli sono più facili da mantenere e funzionano alla grande con il design web modulare
  3. I moduli consentono un facile code splitting con importazioni dinamiche in cui importi solo i moduli di cui hai bisogno in un determinato momento.

Svantaggi:

  1. I moduli da soli non miglioreranno i Core Web Vitals
  2. Importare moduli just-in-time o al volo potrebbe essere lento e peggiorare l'INP 

Metodo 4: Posiziona gli script verso la parte inferiore della pagina

Gli script nel footer vengono messi in coda per il download in un momento successivo. Questo darà la priorità ad altre risorse che si trovano nel documento sopra il tag script.

<html>
   <head></head>
   <body>
      [il contenuto della tua pagina qui]
      <script defer src='javascript.js'></script>
   </body>
</html>

Posizionare i tuoi script in fondo alla pagina è una tecnica interessante. Questo programmerà altre risorse (come le immagini) prima dei tuoi script. Ciò aumenterà la possibilità che siano disponibili per il browser e dipinti sullo schermo prima che i file JavaScript abbiano terminato il download e il thread principale venga bloccato dall'esecuzione dello script. Tuttavia ... nessuna garanzia.

Quando usarlo:

Quando i tuoi script hanno già prestazioni abbastanza buone ma vuoi dare una leggera priorità ad altre risorse come immagini e webfont.

Vantaggi:

  1. Posizionare gli script in fondo alla pagina non richiede molta conoscenza.
  2. Se fatto correttamente non c'è rischio che questo rompa la tua pagina

Svantaggi:

  1. Gli script Critical potrebbero essere scaricati ed eseguiti in un secondo momento
  2. Non risolve alcun problema JavaScript sottostante

Metodo 5: Inietta gli script

Gli script iniettati vengono trattati come script async. Vengono scaricati in parallelo e vengono eseguiti immediatamente dopo il download.

<script>
    const loadScript = (scriptSource) => {
        const script = document.createElement('script');
        script.src = scriptSource;
        document.head.appendChild(script);
    }

    // chiama la funzione loadscript che inietta 'javascript.js'
    loadScript('javascript.js');
</script>

Da una prospettiva dei Core Web Vitals questa tecnica è esattamente la stessa dell'utilizzo di <script async>.

Quando usarlo:

Questo metodo è spesso utilizzato da script di terze parti che si attivano il prima possibile. La chiamata di funzione rende facile incapsulare e comprimere il codice.

Vantaggi:

  1. Codice contenuto che inietta uno script async.

Svantaggi:

  1. DOMContentLoaded potrebbe verificarsi sia prima che dopo il caricamento dello script.
  2. L'ordine di esecuzione degli script sarà sconosciuto in anticipo.
  3. Non puoi usarlo su script che dipendono da altri script async o differiti

Metodo 6: Inietta gli script in un momento successivo

Gli script nice-to-have non dovrebbero a mio parere mai essere caricati in modo differito. Dovrebbero essere iniettati nel momento più opportuno. Nell'esempio seguente lo script verrà eseguito dopo che il browser ha inviato l'evento 'load'.

<script>
window.addEventListener('load', function () {
  // vedi il metodo 5 per la funzione loadscript
  loadScript('javascript.js');
});
</script>

Questa è la prima tecnica che migliorerà in modo affidabile il Largest Contentful Paint. Tutte le risorse importanti, incluse le immagini, verranno scaricate quando il browser attiva l'evento 'load'. Questo potrebbe introdurre tutti i tipi di problemi perché potrebbe volerci molto tempo prima che l'evento load venga chiamato.

Quando usarlo:

Per gli script nice-to-have che non hanno motivo di influenzare le paint metrics.

Vantaggi:

  1. Non competerà per le risorse critiche perché inietterà lo script una volta che la pagina e le sue risorse si saranno caricate

Svantaggi:

  1. Se la tua pagina è mal progettata dal punto di vista dei Core Web Vitals, potrebbe volerci molto tempo prima che la pagina invii l'evento 'load'
  2. Devi stare attento a non applicarlo a script critici (come lazy loading, menu ecc.)

Metodo 7: Cambia il tipo di script (e poi cambialo di nuovo)

Se un tag script si trova da qualche parte sulla pagina che 1. ha un attributo type e 2. l'attributo type non è "text/javascript" lo script non verrà scaricato ed eseguito da un browser. Molti JavaScript Loader (come il RocketLoader di CloudFlare) si basano su questo principio. L'idea è piuttosto semplice ed elegante.

Per prima cosa tutti gli script vengono riscritti così:

<script  src="javascript.js"></script>

Quindi, ad un certo punto durante il processo di caricamento, questi script vengono convertiti in 'normali javascript'.

Quando usarlo:

Questo non è un metodo che raccomanderei. Risolvere l'impatto di JavaScript richiederà molto di più che semplicemente spostare ogni script un po' più in basso nella coda. D'altra parte, se hai poco controllo sugli script in esecuzione sulla pagina o hai una conoscenza insufficiente di JavaScript, questa potrebbe essere la tua migliore scommessa.

Vantaggi:

  1. È facile, basta abilitare rocket loader o un altro plugin e tutti i tuoi script vengono ora eseguiti in un momento un po' successivo.
  2. Probabilmente risolverà le tue paint metrics a condizione che tu non abbia utilizzato il lazy loading basato su JS.
  3. Funzionerà per script inline ed esterni.

Svantaggi:

  1. Non avrai un controllo granulare su quando gli script vengono eseguiti
  2. Script scritti male potrebbero rompersi
  3. Usa JavaScript per sistemare JavaScript
  4. Non fa nulla per correggere gli script in esecuzione prolungata

Metodo 8: Usa l'intersection observer

Con l'intersection observer puoi eseguire una funzione (che in questo caso carica un JavaScript esterno) quando un elemento scorre nel viewport visibile.

<script>
const handleIntersection = (entries, observer) => {
    if (entries?.[0].isIntersecting) {
        // carica il tuo script o esegui un'altra
           funzione come attivare un elemento in lazy load
        loadScript('javascript.js');

        // rimuovi l'osservatore
        observer.unobserve(entries?.[0].target);
    }
};
const Observer = new window.IntersectionObserver()
Observer.observe(document.querySelector('footer'));
</script>

Questo è di gran lunga il metodo più efficace per differire JavaScript che ci sia. Carica solo gli script di cui hai bisogno, appena prima che tu ne abbia bisogno. Sfortunatamente la vita reale è raramente così pulita e non molti script possono essere legati a un elemento che scorre nella visuale.

Quando usarlo:

Usa questa tecnica il più possibile! Ogni volta che uno script interagisce solo con un componente fuori schermo (come una mappa, uno slider, un modulo) questo è il modo migliore per iniettare questo script.

Vantaggi:

  1. Non interferirà con i Core Web Vitals LCP e FCP
  2. Non inietterà mai script che non vengono utilizzati. Questo migliorerà l'INP

Svantaggi:

  1. Non dovrebbe essere usato con componenti che potrebbero trovarsi nel viewport visibile
  2. È più difficile da mantenere rispetto a un semplice <script src="...">
  3. Potrebbe introdurre un layout shift

Metodo 9: Usa readystatechange

document.readystate può essere usato come alternativa agli eventi 'DOMContentloaded' e 'load'. Il readystate 'interactive' è di solito un buon posto per richiamare script critici che devono modificare il DOM o aggiungere gestori di eventi. 
Il readystate 'complete' è un buon posto per richiamare script che sono meno critici.

document.addEventListener('readystatechange', (event) => {
  if (event.target.readyState === 'interactive') {
    initLoader();
  } else if (event.target.readyState === 'complete') {
    initApp();
  }
});

Metodo 10: Usa setTimeout con timeout nullo

setTimeout è un metodo disapprovato ma fortemente sottovalutato nella community del pagespeed. setTimeout ha una cattiva reputazione perché spesso viene usato in modo improprio.  Molti sviluppatori credono che setTimeout possa essere utilizzato solo per ritardare l'esecuzione dello script del numero di millisecondi impostato. Sebbene questo sia vero, setTimeout fa in realtà qualcosa di molto più interessante. Crea una nuova attività alla fine dell'event loop del browser. Questo comportamento può essere utilizzato per programmare le tue attività in modo efficace. Può anche essere usato per spezzare attività lunghe in attività più piccole e separate

<script>
   setTimeout(() => {
       // carica uno script o esegui un'altra funzione
       console.log('- Vengo chiamato da un timeOut() di 0ms')
    }, 0);

   console.log("- Ero l'ultimo della fila ma eseguito per primo")
   /*
      Output:
      - Ero l'ultimo della fila ma eseguito per primo
      - Vengo chiamato da un timeOut() di 0ms
   */
</script>

Quando usarlo:

setTimeout crea un nuovo task nell'event loop del browser. Usalo quando il tuo thread principale viene bloccato da molte chiamate di funzione che vengono eseguite in sequenza.

Vantaggi:

  1. Può spezzare codice in esecuzione prolungata in parti più piccole.

Svantaggi:

  1. setTimeout è un metodo piuttosto grezzo e non offre priorità per gli script importanti.
  2. Aggiungerà il codice da eseguire alla fine del loop

Metodo 11: Usa setTimeout con un timeout

Le cose si fanno ancora più interessanti quando chiamiamo setTimeout con un timeout di più di 0ms

<script>
   setTimeout(() => {
       // carica uno script o esegui un'altra funzione
       console.log('- Vengo chiamato da un timeOut() di 10ms')
    }, 10);

   setTimeout(() => {
       // carica uno script o esegui un'altra funzione
       console.log('- Vengo chiamato da un timeOut() di 0ms')
    }, 0);

   console.log("- Ero l'ultimo della fila ma eseguito per primo")
   /*
      Output:
      - Ero l'ultimo della fila ma eseguito per primo
      - Vengo chiamato da un timeOut() di 0ms
      - Vengo chiamato da un timeOut() di 10ms
   */
</script>

Quando usarlo:

Quando hai bisogno di un metodo facile per programmare uno script dopo l'altro, un piccolo timeout farà al caso tuo

Vantaggi:

  1. Supportato su tutti i browser

Svantaggi:

  1. Non offre una programmazione avanzata

Metodo 12: Usa una promise per impostare un microtask

Anche la creazione di un micro-task è un modo interessante per programmare JavaScript. I micro-task vengono programmati per l'esecuzione immediatamente dopo che il loop di esecuzione corrente è terminato.

<script>
   const myPromise = new Promise((resolve, reject) => {
      resolve();
   }).then(
      () => {
         console.log('- Sono stato programmato dopo una promise')
         }
   );
   console.log("- Ero l'ultimo della fila ma eseguito per primo")

   /*
      Output:
      - Ero l'ultimo della fila ma eseguito per primo
      - Sono stato programmato dopo una promise
   */
</script>

Quando usarlo:

Quando un task deve essere programmato immediatamente dopo un altro task. 

Vantaggi:

  1. Il microtask verrà programmato immediatamente dopo che il task ha finito di essere eseguito.
  2. Un microtask può essere utilizzato per ritardare parti di codice JavaScript meno importanti nello stesso evento. 

Svantaggi:

  1. Non dividerà il thread principale in parti più piccole. Il browser non avrà alcuna possibilità di rispondere all'input dell'utente.
  2. Probabilmente non avrai mai bisogno di usare i microtask per migliorare i Core Web Vitals a meno che tu non sappia già esattamente cosa stai facendo.

Metodo 13: Usa un microtask

Lo stesso risultato può essere ottenuto utilizzando queueMicrotask(). Il vantaggio dell'utilizzo di queueMicrotask() rispetto a una promise è che è leggermente più veloce e non devi gestire le tue promise.

<script>
   queueMicrotask(() => {
      console.log('- Sono un microtask')
   })

   console.log("- Ero l'ultimo della fila ma eseguito per primo")

   /*
      Output:
      - Ero l'ultimo della fila ma eseguito per primo
      - Sono un microtask
   */
</script>


Metodo 14: Usa requestIdleCallback

Il metodo window.requestIdleCallback() mette in coda una funzione che deve essere chiamata durante i periodi di inattività di un browser. Ciò consente agli sviluppatori di eseguire attività in background e a bassa priorità sul loop dell'evento principale, senza influire su eventi critici per la latenza come l'animazione e la risposta all'input. Le funzioni sono generalmente chiamate nell'ordine first-in-first-out; tuttavia, le callback che hanno un timeout specificato possono essere chiamate fuori ordine se necessario al fine di eseguirle prima che scada il timeout.

<script>
requestIdleCallback(() => {
    const script = document.createElement('script');
    script.src = 'javascript.js';
    document.head.appendChild(script);
});
</script>

Quando usarlo:

Usalo per script che sono Nice to have o per gestire attività non critiche dopo l'input dell'utente

Vantaggi:

  1. Esegui JavaScript con un impatto minimo sull'utente
  2. Molto probabilmente migliorerà l'INP

Svantaggi:

  1. Nessuna garanzia che il codice verrà mai attivato 

Metodo 15: Usa postTask

Il metodo scheduler.postTask() consente agli utenti di specificare opzionalmente un ritardo minimo prima che il task venga eseguito, una priorità per il task e un segnale che può essere usato per modificare la priorità del task e/o interrompere il task. Restituisce una promise che viene risolta con il risultato della funzione di callback del task, o rifiutata con il motivo dell'interruzione o un errore lanciato nel task.

<script>
scheduler.postTask(() => {
    const script = document.createElement('script');
    script.src = 'javascript.js';
    document.head.appendChild(script);
}, { priority: 'background' });
</script>

Quando usarlo:

postTask è l'API giusta con cui programmare gli script quando hai bisogno di un controllo granulare sulla priorità.

Vantaggi:

  1. Controllo completo sulla programmazione dell'esecuzione di JavaScript!

Svantaggi:

  1. Non supportato in Safari. Supportato in Chrome 94+, Edge 94+ e Firefox 142+. Usa il rilevamento delle funzionalità e un fallback a setTimeout per una copertura completa.

Metodo 16: Usa scheduler.yield()

scheduler.yield() è il modo più recente per suddividere le attività lunghe. Restituisce una promise che si risolve in un nuovo task, dando al browser la possibilità di rispondere all'input dell'utente tra blocchi di lavoro. A differenza di setTimeout, la continuazione ottiene la priorità su altri task in coda, in modo che il tuo codice riprenda da dove si era interrotto senza essere spinto in fondo alla fila.

<script>
async function processItems(items) {
    for (const item of items) {
        doWork(item);
        await scheduler.yield();
    }
}
</script>

Questo è in assoluto il miglior strumento per migliorare l'INP. I task lunghi che bloccano il thread principale per centinaia di millisecondi possono essere divisi in pezzi più piccoli, ciascuno separato da un punto di rilascio (yield). Il browser può gestire l'input dell'utente in ogni punto di rilascio. Per una spiegazione pratica di questo pattern, vedi come cedere il controllo al thread principale (yield to main thread).

Safari non supporta ancora scheduler.yield(), quindi includi sempre un fallback:

<script>
function yieldToMain() {
    if (globalThis.scheduler?.yield) {
        return scheduler.yield();
    }
    return new Promise(resolve => {
        setTimeout(resolve, 0);
    });
}

async function processItems(items) {
    for (const item of items) {
        doWork(item);
        await yieldToMain();
    }
}
</script>

Quando usarlo:

Usalo ogni volta che hai del JavaScript in esecuzione prolungata che blocca il thread principale. È l'approccio raccomandato per migliorare l'INP sui gestori di interazione e su qualsiasi codice che elabora dati in un loop.

Vantaggi:

  1. Spezza le attività lunghe senza perdere il tuo posto nella coda
  2. La continuazione viene eseguita prima di altri task in coda (a differenza di setTimeout che va in fondo alla fila)
  3. Migliora direttamente l'INP dando al browser la possibilità di rispondere all'input dell'utente

Svantaggi:

  1. Non supportato in Safari. Supportato in Chrome 129+, Edge 129+ e Firefox 142+.
  2. Richiede un fallback per una copertura completa del browser (setTimeout funziona come polyfill)

Dopo aver applicato queste tecniche, verifica il miglioramento con il Real User Monitoring. I punteggi di Lighthouse sono un punto di partenza, ma i dati sul campo di utenti reali sono ciò che Google usa per il posizionamento. CoreDash traccia l'INP e tutti i Core Web Vitals dai visitatori reali, in modo che tu possa vedere se la tua strategia di deferimento sta effettivamente funzionando in produzione.

About the author

Arjen Karel is a web performance consultant and the creator of CoreDash, a Real User Monitoring platform that tracks Core Web Vitals data across hundreds of sites. He also built the Core Web Vitals Visualizer Chrome extension. He has helped clients achieve passing Core Web Vitals scores on over 925,000 mobile URLs.

Pinpoint the route, device, and connection that fails.

CoreDash segments every metric by route, device class, browser, and connection type. Real time data. Not the 28 day average Google gives you.

Explore Segmentation
16 metodi per differire o programmare JavaScriptCore Web Vitals 16 metodi per differire o programmare JavaScript