- La posizione conta
- Async e Defer
- Confronto delle prestazioni
- No defer o async, nella testa
- Nessuno defer o async, nel corpo
- Con async, nella testa
- Con defer, nella testa
- Blocking parsing
- Blocking rendering
- domInteractive
- Tenere le cose in ordine
- Dimmi solo il modo migliore
Quando si carica uno script su una pagina HTML, bisogna stare attenti a non danneggiare le prestazioni di caricamento della pagina.
Uno script è tradizionalmente incluso nella pagina in questo modo:
<script src="https://flaviocopes.com/javascript-async-defer/script.js"></script>
ogni volta che il parser HTML trova questa linea, viene fatta una richiesta per recuperare lo script, e lo script viene eseguito.
Una volta che questo processo è terminato, il parsing può riprendere, e il resto dell’HTML può essere analizzato.
Come potete immaginare, questa operazione può avere un enorme impatto sul tempo di caricamento della pagina.
Se lo script impiega un po’ più tempo del previsto per caricarsi, per esempio se la rete è un po’ lenta o se siete su un dispositivo mobile e la connessione è un po’ scadente, il visitatore probabilmente vedrà una pagina bianca finché lo script non sarà caricato ed eseguito.
La posizione conta
Quando impari l’HTML per la prima volta, ti viene detto che i tag script vivono nel tag <head>
:
<html> <head> <title>Title</title> <script src="https://flaviocopes.com/javascript-async-defer/script.js"></script> </head> <body> ... </body></html>
Come ti ho detto prima, quando il parser trova questa linea, va a prendere lo script e lo esegue. Poi, dopo che ha finito questo compito, va ad analizzare il corpo.
Questo non va bene perché viene introdotto un sacco di ritardo. Una soluzione molto comune a questo problema è mettere il tag script
in fondo alla pagina, appena prima del tag di chiusura </body>
.
In questo modo, lo script viene caricato ed eseguito dopo che tutta la pagina è già stata analizzata e caricata, il che è un enorme miglioramento rispetto all’alternativa head
.
Questa è la cosa migliore che puoi fare se hai bisogno di supportare i vecchi browser che non supportano due caratteristiche relativamente recenti di HTML: async
e defer
.
Async e Defer
Async e defer sono entrambi attributi booleani. Il loro uso è simile:
<script async src="https://flaviocopes.com/javascript-async-defer/script.js"></script>
<script defer src="https://flaviocopes.com/javascript-async-defer/script.js"></script>
se li specifichi entrambi, async
ha la precedenza sui browser moderni, mentre i vecchi browser che supportano defer
ma non async
faranno fallback a defer
.
Questi attributi hanno senso solo quando si usa lo script nella porzione head
della pagina, e sono inutili se si mette lo script nel body
footer come abbiamo visto sopra.
Confronto delle prestazioni
No defer o async, in testa
Ecco come una pagina carica uno script senza defer o async, messo nella porzione head
della pagina:
L’analisi viene messa in pausa finché lo script viene recuperato ed eseguito. Una volta fatto questo, l’analisi riprende.
No defer o async, nel corpo
Ecco come una pagina carica uno script senza defer o async, messo alla fine del tag body
, appena prima della chiusura:
L’analisi viene fatta senza alcuna pausa, e quando finisce, lo script viene recuperato ed eseguito. L’analisi viene fatta prima che lo script venga scaricato, quindi la pagina appare all’utente molto prima dell’esempio precedente.
Con async, nell’head
Ecco come una pagina carica uno script con async
, messo nel tag head
:
Lo script viene recuperato in modo asincrono, e quando è pronto l’analisi HTML viene messa in pausa per eseguire lo script, poi viene ripresa.
Con defer, nell’head
Ecco come una pagina carica uno script con defer
, messo nel tag head
:
Lo script viene recuperato in modo asincrono, e viene eseguito solo dopo che l’analisi HTML è terminata.
L’analisi finisce proprio come quando mettiamo lo script alla fine del tag body
, ma nel complesso l’esecuzione dello script finisce molto prima, perché lo script è stato scaricato in parallelo con l’analisi dell’HTML.
Quindi questa è la soluzione vincente in termini di velocità 🏆
Blocking parsing
async
blocca l’analisi della pagina mentre defer
no.
Blocking rendering
Né async
né defer
garantiscono nulla sul blocco del rendering. Questo dipende da te e dal tuo script (per esempio, assicurandoti che i tuoi script vengano eseguiti dopo l’evento onLoad
).
domInteractive
Gli script contrassegnati defer
vengono eseguiti subito dopo l’evento domInteractive
, che avviene dopo che l’HTML è stato caricato, analizzato e il DOM è stato costruito.
CSS e immagini a questo punto devono ancora essere analizzati e caricati.
Una volta fatto questo, il browser emetterà l’evento domComplete
e poi onLoad
.
domInteractive
è importante perché il suo tempo è riconosciuto come una misura della velocità di caricamento percepita. Vedi il MDN per saperne di più.
Tenere le cose in ordine
Un altro caso pro defer
: gli script marcati async
vengono eseguiti in ordine casuale, quando diventano disponibili. Gli script segnati defer
sono eseguiti (dopo che l’analisi è stata completata) nell’ordine in cui sono definiti nel markup.
Dimmi solo il modo migliore
La cosa migliore da fare per accelerare il caricamento della tua pagina quando usi gli script è metterli nel head
, e aggiungere un attributo defer
al tuo tag script
:
<script defer src="https://flaviocopes.com/javascript-async-defer/script.js"></script>
Questo è lo scenario che attiva l’evento domInteractive
più veloce.
Considerando i pro di defer
, sembra una scelta migliore di async
in una varietà di scenari.
A meno che non vi vada bene ritardare il primo rendering della pagina, assicuratevi che quando la pagina viene analizzata il JavaScript che volete sia già stato eseguito.
Scaricate il mio manuale gratuito di JavaScript per principianti
Altri tutorial per browser:
- Alcuni trucchi utili disponibili in HTML5
- Come ho fatto funzionare offline un sito web basato su CMSbasato su CMS funziona offline
- La guida completa alle Progressive Web Apps
- La Fetch API
- La guida Push API
- Il canale di messaggistica API
- Il tutorial sui service worker
- La guida alle API di cache
- La guida alle API di notifica
- Tuffarsi nell’IndexedDB
- Le API di selezione: querySelector e querySelectorAll
- Carica efficacemente JavaScript con defer e async
- Il Document Object Model (DOM)
- L’API di archiviazione web: archiviazione locale e di sessione
- Impara come funzionano i cookie HTTP
- L’API della cronologia
- Il formato immagine WebP
- XMLHttpRequest (XHR)
- Un tutorial approfondito su SVG
- Cosa sono gli URL di dati
- Roadmap per imparare la piattaforma web
- CORS, Cross-Origin Resource Sharing
- Web Workers
- La guida requestAnimationFrame()
- Cos’è il Doctype
- Lavoro con la DevTools Console e l’API Console
- L’API di sintesi vocale
- Come aspettare l’evento DOM ready in semplice JavaScript
- Come aggiungere una classe ad un elemento DOM elemento DOM
- Come fare un loop sugli elementi DOM da querySelectorAll
- Come rimuovere una classe da un elemento DOM
- Come controllare se un elemento DOM ha una classe
- Come cambiare il valore di un nodo DOM
- Come aggiungere un evento click ad una lista di elementi DOM restituiti da querySelectorAll
- WebRTC, la Real Time Web API
- Come ottenere la posizione di scorrimento di un elemento in JavaScript
- Come sostituire un elemento DOM
- Come accettare solo immagini in un campo file di input
- Perché usare una versione di anteprima di un browser?
- L’oggetto Blob
- L’oggetto File
- L’oggetto FileReader
- L’oggetto FileList
- ArrayBuffer
- ArrayBufferView
- L’oggetto URL
- Typed Arrays
- L’oggetto DataView
- L’API BroadcastChannel
- L’API Streams
- L’oggetto FormData
- L’oggetto Navigator
- Come usare l’API Geolocation
- Come usare getUserMedia()
- Come usare il Drag and Drop API
- Come lavorare con lo scorrimento nelle pagine web
- Gestione dei moduli in JavaScript
- Eventi della tastiera
- Eventi del mouse eventi
- Eventi touch
- Come rimuovere tutti i figli da un elemento DOM
- Come creare un attributo HTML usando vanilla Javascript
- Come controllare se una checkbox è selezionata usando JavaScript?
- Come copiare negli appunti usando JavaScript
- Come disabilitare un pulsante usando JavaScript
- Come rendere una pagina modificabile nel browser
- Come ottenere valori di query string in JavaScript con URLSearchParams
- Come rimuovere tutti i CSS da una pagina in una volta sola
- Come usare insertAdjacentHTML
- Safari, avvertire prima di uscire
- Come aggiungere un’immagine al DOM usando JavaScript
- Come resettare un modulo
- Come usare Google Fonts