async e defer: pagine più veloci con il caricamento degli script ottimizzato

Francesco Sciuti
Devmy
Published in
4 min readNov 5, 2019

Sappiamo tutti quanto Google e i nostri utenti siano oggi estremamente esigenti per quel che riguarda la velocità delle pagine delle nostre pagine: bastano pochi secondi di ritardo e il visitatore se n’è già andato, perso nel mare di siti che ci fanno concorrenza o imbambolato a guardare l’ennesima galleria di gatti su Instagram.

Uno dei “colli di bottiglia” più comuni è il caricamento degli script JavaScript esterni: ormai ogni pagina ne carica un numero impressionante(fra librerie esterne, analytics di ogni sorta, plugin e altre stregonerie varie), script che a volte si trovano su CDN non sempre velocissime o che possono essere di qualche centinaio di KB e così mentre la pagina li carica tutto tace ed è fermo — tranne l’impazienza dell’utente.

Una delle prime soluzioni per ovviare a questo problema sono alcune tecniche di caricamento degli script in maniera “asincrona”, ovvero non bloccando il download del resto della pagina ma facendolo in parallelo. Fino a qualche tempo fa la soluzione si appoggiava a codice a dir poco complesso da scrivere e specifico per ogni browser ma già da davvero tanto tempo HTML5 ci viene in aiuto con due semplicissime paroline che possiamo usare come attributi del tag <script>:

async & defer

In maniera estremamente veloce e facile possiamo aggiungere uno di questi attributi al tag <script>, così:

<script async src=”myAsyncScript.js” onload=”myAsyncInit()”></script>
<script defer src=”myDeferScript.js” onload=”myDeferInit()”></script>

In questo modo, i due script saranno caricati in maniera asincrona (vedremo dopo la differenza fra i due) ed al loro caricamento verrà richiamata la funzione relativa (ad esempio la funzione che deve eseguire lo script).

Il vantaggio di questa soluzione è facile ed immediato: se prima uno script ci metteva 2 secondi a caricare e l’altro altri 2 la pagina veniva bloccata per 4 secondi. Adesso i due script vengono caricati in maniera “asincrona” e quindi la pagina può iniziare ad essere mostrata subito, senza aspettare nulla.

Un’ulteriore vantaggio dell’approccio asincrono è che se per caso uno degli script non fosse raggiungibile (ad esempio perchè la CDN è “caduta”) la nostra pagina sarebbe comunque visibile e non bloccheremmo nulla.
N.B. A tal proposito sarebbero anche disponibili ulteriori attributi che valuteremo in un prossimo articolo (qualcuno ha detto rel=”preconnect” o rel=”dns-prefetch”?).

La differenza fra async e defer

La differenza fra le due modalità è sottile ma estremamente importante.

Async

L’attributo async sui tags script consente l’esecuzione del file JavaScript esterno quando è completamente disponibile, senza ritardare prima il caricamento della pagina.

Usando async lo script quindi viene caricato in asincronia mentre viene eseguito il parsing dell’HTML, senza rispettare l’ordine in cui appare nella pagina e prima dell’evento window.load.
Quindi ad esempio uno script che richiamiamo nell’<head> e uno che abbiamo nel <footer> potrebbero essere eseguiti “al contrario” (cioè prima quello nel footer e poi quello nell’head).
Quando lo script finisce il proprio caricamento, il parsing dell’HTML viene bloccato e viene eseguito lo script.

Defer

L’attributo defer sui tags script consente l’esecuzione del file JavaScript esterno quando a fine del caricamento del DOM, e quindi senza ritardare il caricamento della pagina.

Con defer, invece, diciamo al browser di richiamare gli script nell’ordine in cui appaiono nella pagina — quindi prima verrà eseguito lo script nell’<head> e poi quello nel <footer>: l’esecuzione comincerà non appena il parsing è completo, prima che l’evento DOMContentLoaded sia lanciato.

In generale, è necessario utilizzare sempre async o defer per script di terze parti (a meno che lo script non esegua le operazioni necessarie per il critical rendering path):

Utilizzare async se è importante che lo script venga eseguito prima nel processo di caricamento. Ciò potrebbe includere alcuni script di analisi, ad esempio.

Usare defer per risorse meno critiche. Un lettore video che è above the fold, ad esempio.

Compatibilità e avvertenze

Ampiamente supportati da tutti i browser, come è possibile vedere su CanIUse.

Conclusioni

Mi auguro che questi attributi possano aiutarvi nei momenti difficili in cui le pagine sono tanto lunghe da caricare!
Per suggerimenti (o aggiunte perché no!), critiche, insulti, complimenti, regali di gadget di Batman e ricchi premi…non esitate a scrivere nei commenti!

Felice asincronia ed alla prossima!

Segui Acadevmy — Software Factory & Learning su Medium, Twitter e Facebook per contattarci o tenerti aggiornato sul mondo dello sviluppo Frontend e DevOps.

--

--

Francesco Sciuti
Devmy
Editor for

CEO@Acadevmy, Google Certified Developer, Projects Manager, Software Engineer, Speaker/Evangelist/Trainer