Skip to content

Le dipendenze Javascript sono per loro natura risorse di blocco, più precisamente parser blocking. Parser blocking significa che al momento in cui il parser del browser inizia la lettura del codice HTML ed incontra uno script, sospende tutte le operazioni di lettura e rendering per poterne eseguire il codice. Una pagina HTML ha solitamente più dipendenza JS, queste continue interruzioni possono rallentare in modo considerevole la velocità caricamento e rendering della pagina stessa. Se in più lo script è esterno al sito web, il momento di stallo sarà allungato dai tempi di download della risorsa.

Per ridurre i blocchi di rendering causati da Javascript possono essere utilizzare diverse tecniche tra cui l’utilizzo degli attributi HTML async e defer. Ma qual è la differenza tra async e defer? In quale contesto va utilizzato uno anziché l’altro?

Render-Blocking JavaScript

Render-Blocking JavaScript è un termine che non ti suona nuovo? Lo vedi sempre sui tuoi report di Google PageSpeed Insights o GTmetrix?

Le dipendenze JavaScript presenti nel tuo HTML possono ritardare la visualizzazione del contenuto della pagina perché il browser deve prima scaricarle ed interpretarle.

Il problema del “Render-blocking” deriva da un comportamento predefinito del browser web: vuole ricevere e elaborare completamente tutto ciò che è indicato nell’head dell’HTML prima di iniziare il rendering della pagina. In altre parole, la presenza di file esterni in JavaScript blocca la funzione fondamentale del browser: disegnare la pagina. Il risultato può essere un sito lento e utenti frustrati.

Con gli attributi async e defer è possibile risolvere questo problema rimuovendo o ritardando il blocco.

L’elemento HTML <script src=”script.js”></script> consente di definire quando il browser deve iniziare ad eseguire il codice JavaScript nella tua pagina. Gli attributi async e defer sono stati aggiunti al WebKit a Settembre 2010.

Gli attributi async e defer per gli elementi script sono utili per ottimizzare il caricamento della pagina evitando stop nel rendering della pagina HTML causati da elementi di blocco come dipendenze JavaScript.

<script>

Cominciamo col definire che cosa succede quando si richiama uno <script> senza alcun attributo. Il file HTML viene analizzato fino a quando non viene richiamata una dipendenza (uno <script>), a quel punto l’analisi si ferma ed il browser inizia a scaricare il file (se è esterno). Lo <script> verrà eseguito subito dopo il download, il rendering dell’HTML continuerà soltanto dopo che lo <script> viene eseguito. Per i server lenti e pesanti richiamare <script> in questo modo significa che la visualizzazione della pagina web subirà dei rallentamenti.

<script async>

  • L’attributo async evita di interrompere il rendering dell’HTML durante il download dello <script>, che di fatto avviene in parallelo
  • Lo <script> viene eseguito subito dopo il download
  • Il parsing della pagina viene messo in pausa soltanto mentre lo <script> viene eseguito

Non ti importa quando lo <script> sarà disponibile? async è il migliore dei due metodi: il parsing del codice HTML può continuare e lo <script> verrà eseguito non appena è pronto. Consiglio questo per gli <script> come Google Analytics.

<script defer>

  • L’attributo defer evita di interrompere il rendering dell’HTML durante il download dello <script>, che di fatto avviene in parallelo
  • Lo <script> viene eseguito subito dopo il parsing della pagina HTML
  • Il parsing della pagina non viene mai messo in pausa

Un effetto positivo di questo attributo è che il DOM (Document Object Model: nativamente supportato dai browser per modificare gli elementi di un documento HTML, DOM è un modo per accedere e aggiornare dinamicamente il contenuto, la struttura e lo stile dei documenti) sarà già pronto per lo <script>.

asinc e defer assieme

È possibile usare entrambi gli attributi assieme? Secondo lo standard, si è possibile.
Cito il testo originale:

The defer attribute may be specified even if the async attribute is specified, to cause legacy Web browsers that only support defer (and not async) to fall back to the defer behavior instead of the synchronous blocking behavior that is the default.

Che tradotto vuol dire: L’attributo defer può essere specificato anche in presenza dell’attributo async, per permettere ai browser legacy (datati) che supportano solo il defer (e non async) di posticipare download ed esecuzione del JS invece di seguire il comportamento predefinito di blocco sincrono.

Quale attributo è meglio usare?

In genere si desidera utilizzare async, ove possibile, come seconda scelta defer ed infine nessun attributo. Ecco alcune regole generali da seguire:

  • Se lo <script> è modulare e non si basa su altri <script>, sarebbe meglio utilizzare async
  • Se lo <script> si basa su altri <script> o viene invocato da un altro <script>, sarebbe meglio utilizzare defer
  • Se lo <script> è di piccole dimensioni ed è invocato da uno <script> asincrono, sarebbe meglio utilizzare uno <script> in linea senza attributi posto sopra gli <script> asincroni

Di solito la libreria jQuery non è un buon candidato per l’attributo async perché altri <script> potrebbero dipendere da quella libreria (molto utilizzata). Puoi usare async ma devi assicurarti che gli altri <script> non vengano eseguiti fino al caricamento di jQuery.

Aggiungere attributi Defer & Async agli script di WordPress

Per applicare l’attributo async alle dipendenze JavaScript di un sito WordPress puoi usare questa funzione da inserire nel file functions.php del tuo tema.

/*enable async script call*/
function add_async_forscript($url)
{
    if (strpos($url, '#asyncload')===false)
        return $url;
    else if (is_admin())
        return str_replace('#asyncload', '', $url);
    else
        return str_replace('#asyncload', '', $url)."' async='async"; 
}
add_filter('clean_url', 'add_async_forscript', 11, 1);

/*so you can add async to any script without code changes, just add #asyncload to script url as:*/
wp_enqueue_script('dcsnt', '/js/jquery.social.media.tabs.1.7.1.min.js#asyncload' )

Fino ad oggi gli sviluppatori WordPress non avevano la possibilità di inserire gli script in modo ottimale per il semplice fatto che WordPress non aveva un filtro dedicato per aggiungere gli attributi async e defer.

Per fortuna non è più così. Dalla versione 4.1 di WordPress è stato introdotto un nuovo filtro che offre una soluzione per aggiungere attributi async e defer alle dipendenze JavaScript.

Come implementare async e defer su una specifica dipendenza JavaScript

Vediamo prima come applicare l’attributo async oppure defer ad un singolo script di cui conosciamo l’handle (il nome con cui richiamare la dipendenza ad esempio in una funzione).

Prima di tutto devi navigare nel file functions.php o equivalente se ne usi uno aggiuntivo customizzato. Copia e incolla lo script che segue apportando le opportune modifiche.

function add_async_attribute($tag, $handle) {
    if ( 'my-js-handle' !== $handle )
        return $tag;
    return str_replace( ' src', ' async="async" src', $tag );
}
add_filter('script_loader_tag', 'add_async_attribute', 10, 2);

//* If you want to use defer just replace async="async" with defer="defer".
//* You will need to change the handle which will be the first parameter of the enqueue method.
  • my-js-handle: sostituisci questo handle di esempio con il nome dello script che devi ottimizzare
  • async o defer?: sostituisci in riga 4 async=”async” con defer=”defer” per cambiare attributo

I parametri 10, 2 indicano rispettivamente la priorità di esecuzione del filtro ed il numero di argomenti passati alla funzione del filtro.

Come implementare async e defer su più dipendenze JavaScript

Per implementare async o defer a più script contemporaneamente basta usare un array e un foreach. Inserisci in riga 3 tutti gli handle che vuoi gestire all’interno dell’array, in fondo alla pagina trovi la lista degli handle standard usati da WordPress.

Naviga nel file functions.php o equivalente se ne usi uno aggiuntivo customizzato. Copia e incolla lo script che segue apportando le opportune modifiche.

function add_defer_attribute($tag, $handle) {
   // add script handles to the array below
   $scripts_to_defer = array('jquery-migrate', 'hoverIntent', 'superfish', 'superfish-args', 'skip-links', 'wp-embed');
   
   foreach($scripts_to_defer as $defer_script) {
      if ($defer_script === $handle) {
         return str_replace(' src', ' defer="defer" src', $tag);
      }
   }
   return $tag;
}
add_filter('script_loader_tag', 'add_defer_attribute', 10, 2);

//* If you want to use defer just replace async="async" with defer="defer".
//* You will need to change the handle which will be the first parameter of the enqueue method.
  • $scripts_to_defer = array(‘…’, ‘…’);: inserisci tutti gli handle degli script che vuoi ottimizzare come mostrato nell’esempio
  • async o defer?: sostituisci in riga 7 defer=”defer” con async=”async” per cambiare attributo
Applicare defer su script WordPress

Il risultato di questa funzione è il seguente: attributo defer appeso a tutte le dipendenze che ho impostato.

Alcuni handle noti

Sul mio sito (che usa il framework Genesis) ho ottimizzato tutti gli script il cui caricamento può essere ritardato senza impattare sulla funzionalità della pagine e di altri script. Ad esempio jQuery non posso ritardarlo altrimenti gli altri script come superfish, che dipende da jQuery, non viene attivato correttamente e la console di Chrome mostra l’errore.

Di seguito ti indico alcuni handle più noti che puoi usare nelle funzioni mostrate in questa guida. Verifica se sono presenti nel tuo codice HTML e usali nelle funzioni proposte.

Script predefiniti inclusi e registrati da WordPress:

  • Nome dello script – Handle
  • Image Cropper – Image cropper (not used in core, see jcrop)
  • Jcrop – jcrop
  • SWFObject – swfobject
  • SWFUpload – swfupload
  • SWFUpload Degrade – swfupload-degrade
  • SWFUpload Queue – swfupload-queue
  • SWFUpload Handlers – swfupload-handlers
  • jQuery – jquery
  • jQuery Form – jquery-form
  • jQuery Color – jquery-color
  • jQuery Masonry – jquery-masonry
  • Masonry (native Javascript) – masonry
  • jQuery UI Core – jquery-ui-core
  • jQuery UI Widget – jquery-ui-widget
  • jQuery UI Accordion – jquery-ui-accordion
  • jQuery UI Autocomplete – jquery-ui-autocomplete
  • jQuery UI Button – jquery-ui-button
  • jQuery UI Datepicker – jquery-ui-datepicker
  • jQuery UI Dialog – jquery-ui-dialog
  • jQuery UI Draggable – jquery-ui-draggable
  • jQuery UI Droppable – jquery-ui-droppable
  • jQuery UI Menu – jquery-ui-menu
  • jQuery UI Mouse – jquery-ui-mouse
  • jQuery UI Position – jquery-ui-position
  • jQuery UI Progressbar – jquery-ui-progressbar
  • jQuery UI Selectable – jquery-ui-selectable
  • jQuery UI Resizable – jquery-ui-resizable
  • jQuery UI Selectmenu – jquery-ui-selectmenu
  • jQuery UI Sortable – jquery-ui-sortable
  • jQuery UI Slider – jquery-ui-slider
  • jQuery UI Spinner – jquery-ui-spinner
  • jQuery UI Tooltips – jquery-ui-tooltip
  • jQuery UI Tabs – jquery-ui-tabs
  • jQuery UI Effects – jquery-effects-core
  • jQuery UI Effects – Blind – jquery-effects-blind
  • jQuery UI Effects – Bounce – jquery-effects-bounce
  • jQuery UI Effects – Clip – jquery-effects-clip
  • jQuery UI Effects – Drop – jquery-effects-drop
  • jQuery UI Effects – Explode – jquery-effects-explode
  • jQuery UI Effects – Fade – jquery-effects-fade
  • jQuery UI Effects – Fold – jquery-effects-fold
  • jQuery UI Effects – Highlight – jquery-effects-highlight
  • jQuery UI Effects – Pulsate – jquery-effects-pulsate
  • jQuery UI Effects – Scale – jquery-effects-scale
  • jQuery UI Effects – Shake – jquery-effects-shake
  • jQuery UI Effects – Slide – jquery-effects-slide
  • jQuery UI Effects – Transfer – jquery-effects-transfer
  • MediaElement.js (WP 3.6+) – wp-mediaelement
  • jQuery Schedule – schedule
  • jQuery Suggest – suggest
  • ThickBox – thickbox
  • jQuery HoverIntent – hoverIntent
  • jQuery Hotkeys – jquery-hotkeys
  • Simple AJAX Code-Kit – sack
  • QuickTags – quicktags
  • Iris (Colour picker) – iris
  • Farbtastic (deprecated) – farbtastic
  • ColorPicker (deprecated) – colorpicker
  • Tiny MCE – tiny_mce
  • Autosave – autosave
  • WordPress AJAX Response – wp-ajax-response
  • List Manipulation – wp-lists
  • WP Common – common
  • WP Editor – editorremov
  • WP Editor Functions – editor-functions
  • AJAX Cat – ajaxcat
  • Admin Categories – admin-categories
  • Admin Tags – admin-tags
  • Admin custom fields – admin-custom-fields
  • Password Strength Meter – password-strength-meter
  • Admin Comments – admin-comments
  • Admin Users – admin-users
  • Admin Forms – admin-forms
  • XFN – xfn
  • Upload – upload
  • PostBox – postbox
  • Slug – slug
  • Post – post
  • Page – page
  • Link – link
  • Comment – comment
  • Threaded Comments – comment-reply
  • Admin Gallery – admin-gallery
  • Media Upload – media-upload
  • Admin widgets – admin-widgets
  • Word Count – word-count
  • Theme Preview – theme-preview
  • JSON for JS – json2
  • Plupload Core – plupload
  • Plupload All Runtimes – plupload-all
  • Plupload HTML4 – plupload-html4
  • Plupload HTML5 – plupload-html5
  • Plupload Flash – plupload-flash
  • Plupload Silverlight – plupload-silverlight
  • Underscore js – underscore
  • Backbone js – backbone
  • imagesLoaded – imagesloaded
  • Scriptaculous Root – scriptaculous-root
  • Scriptaculous Builder – scriptaculous-builder
  • Scriptaculous Drag & Drop – scriptaculous-dragdrop
  • Scriptaculous Effects – scriptaculous-effects
  • Scriptaculous Slider – scriptaculous-slider
  • Scriptaculous Sound – scriptaculous-sound
  • Scriptaculous Controls – scriptaculous-controls
  • Scriptaculous – scriptaculous
  • Prototype Framework – prototype

Fammi sapere nei commenti se sei riuscito a posticipare il caricamento dei tuoi JavaScript e come questa modifica ha impattato sui tempi di caricamento. A presto!

Articoli correlati

Autore

Commenti |5

Lascia un commento Lascia un commento
  1. Daniel 1 commento

    Grazie per la spiegazione, è proprio quello che cercavo!

    1. Giovanni Sacheli 754 risposte

      Grazie a te Daniel per aver lasciato il commento.

  2. Roberto 1 commento

    Ciao, async e defer vale solo per gli script che si trovano nell’head?
    Per google tag manager come si fa ad aggiunge defer? O si lascia cosi come è?
    In generale basta aggiungere async o defer dopo script?
    Scusatemi ma non sono familiare con gli script! Chiedo per sito in html …no WP

    1. Giovanni Sacheli 754 risposte

      Ciao Roberto, lo script di tag manager è già asincrono e non serve modificarlo. In genere devi testare sia async che defer per trovare la soluzione migliore che non rompe le funzionalità degli script.

  3. Alessandro Romano 1 commento

    Sei sempre un grande. ;)

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Ultimi articoli aggiornati

Richiedi un preventivo SEO e Google Ads

Porta il tuo sito web al livello successivo con l’expertise di EVE Milano. La nostra agenzia di Search Marketing ha ricevuto oltre 1123 richieste di preventivo, un segnale chiaro della fiducia che imprenditori e manager, come te, ripongono nella nostra specializzazione tecnica e verticale nella SEO e PPC. Se la tua organizzazione cerca competenze specifiche per emergere nei risultati di Google, noi siamo pronti a fornire quel valore aggiunto. Affidati alla nostra esperienza per fare la differenza.
Richiedi un preventivo

Non perderti altre guide, iscriviti per ricevere un avviso mensile con gli aggiornamenti del blog!

Iscriviti alla newsletter!

Informativa sui cookies

Noi e terze parti selezionate utilizziamo cookie o tecnologie simili per finalità tecniche e, con il tuo consenso, anche per le finalità di esperienza e misurazione come specificato nella cookie policy. Puoi liberamente prestare, rifiutare o revocare il tuo consenso, in qualsiasi momento, accedendo al pannello delle preferenze. Il rifiuto del consenso può rendere non disponibili le relative funzioni. Usa il pulsante “Accetta” per acconsentire. Usa il pulsante “Rifiuta” per continuare senza accettare.