Ecco cosa succede quando un browser carica un sito Web con un <script>
tag su di esso:
- Recupera la pagina HTML (ad esempio index.html)
- Inizia ad analizzare l'HTML
- Il parser rileva un
<script>
tag che fa riferimento a un file di script esterno.
- Il browser richiede il file di script. Nel frattempo, il parser blocca e interrompe l'analisi dell'altro HTML sulla tua pagina.
- Dopo qualche tempo lo script viene scaricato e successivamente eseguito.
- Il parser continua ad analizzare il resto del documento HTML.
Il passaggio 4 causa una brutta esperienza per l'utente. Fondamentalmente il tuo sito Web interrompe il caricamento fino a quando non hai scaricato tutti gli script. Se c'è una cosa che gli utenti odiano, sta aspettando il caricamento di un sito Web.
Perché succede anche questo?
Qualsiasi script può inserire il proprio HTML tramite document.write()
o altre manipolazioni DOM. Ciò implica che il parser deve attendere che lo script sia stato scaricato ed eseguito prima di poter analizzare in sicurezza il resto del documento. Dopotutto, lo script avrebbe potuto inserire il proprio HTML nel documento.
Tuttavia, la maggior parte degli sviluppatori JavaScript non manipola più il DOM durante il caricamento del documento. Invece, aspettano che il documento sia stato caricato prima di modificarlo. Per esempio:
<!-- index.html -->
<html>
<head>
<title>My Page</title>
<script src="my-script.js"></script>
</head>
<body>
<div id="user-greeting">Welcome back, user</div>
</body>
</html>
Javascript:
// my-script.js
document.addEventListener("DOMContentLoaded", function() {
// this function runs when the DOM is ready, i.e. when the document has been parsed
document.getElementById("user-greeting").textContent = "Welcome back, Bart";
});
Poiché il tuo browser non sa che my-script.js non modificherà il documento fino a quando non è stato scaricato ed eseguito, il parser interrompe l'analisi.
Raccomandazione antiquata
Il vecchio approccio alla risoluzione di questo problema consisteva nel mettere i <script>
tag in fondo al tuo <body>
, perché questo assicura che il parser non sia bloccato fino alla fine.
Questo approccio ha il suo problema: il browser non può iniziare a scaricare gli script fino a quando non viene analizzato l'intero documento. Per i siti Web più grandi con script e fogli di stile di grandi dimensioni, essere in grado di scaricare lo script il più presto possibile è molto importante per le prestazioni. Se il tuo sito Web non viene caricato entro 2 secondi, le persone accederanno a un altro sito Web.
In una soluzione ottimale, il browser inizierà a scaricare gli script il più presto possibile, analizzando allo stesso tempo il resto del documento.
L'approccio moderno
Oggi i browser supportano gli attributi async
e defer
sugli script. Questi attributi indicano al browser che è sicuro continuare ad analizzare mentre gli script vengono scaricati.
async
<script src="path/to/script1.js" async></script>
<script src="path/to/script2.js" async></script>
Gli script con l'attributo asincrono vengono eseguiti in modo asincrono. Ciò significa che lo script viene eseguito non appena viene scaricato, nel frattempo senza bloccare il browser.
Ciò implica che è possibile scaricare ed eseguire lo script 2 prima dello script 1.
Secondo http://caniuse.com/#feat=script-async , il 97,78% di tutti i browser lo supporta.
differire
<script src="path/to/script1.js" defer></script>
<script src="path/to/script2.js" defer></script>
Gli script con l'attributo defer vengono eseguiti in ordine (ovvero prima script 1, quindi script 2). Anche questo non blocca il browser.
A differenza degli script asincroni, gli script di differimento vengono eseguiti solo dopo che l'intero documento è stato caricato.
Secondo http://caniuse.com/#feat=script-defer , il 97,79% di tutti i browser lo supporta. Il 98,06% lo supporta almeno in parte.
Una nota importante sulla compatibilità del browser: in alcune circostanze IE <= 9 può eseguire script differiti non funzionanti. Se hai bisogno di supportare quei browser, leggi prima questo !
Conclusione
Lo stato dell'arte attuale è inserire script nel <head>
tag e usare gli attributi async
o defer
. Ciò consente di scaricare gli script il più presto possibile senza bloccare il browser.
La cosa buona è che il tuo sito web dovrebbe comunque essere caricato correttamente sul 2% dei browser che non supportano questi attributi mentre acceleri l'altro 98%.