Come caricare jQuery in modo asincrono su WordPress


manny tuttofare wordpress

L’idea di questo articolo nasce dopo aver letto quello scritto da Maurizio Ceravolo sul caricamento asincrono di jquery utilizzando il loader jQl.

Visto il mio interesse per la WPO ho deciso quindi di fare alcune prove su WordPress e vedere se e come poter utilizzare jQl per rendere asincrono jquery e relative dipendenze, purtroppo però dopo alcuni tentativi e una chiacchierata con Eugenio Petullà (g+) sono arrivato alla conclusione che come metodo non è molto indicato da utilizzare su wp poiché su questo CMS i file js vengono gestiti utilizzando funzioni proprietarie che ci consentono anche di evitare possibili conflitti con altri file js caricati da temi e plugin.

jQl comunque lo trovo un buon metodo da poter utilizzare su pagine stand-alone dove i vari script sono gestiti “manualmente”.

Sicuramente si sarebbe potuto creare un plugin dedicato che utilizzasse questo metodo ma sinceramente ho preferito una strada alternativa e cercare una soluzione esistente con gli strumenti al momento disponibili.

Qui di seguito puoi trovare due discussioni su google plus dove se n’è parlato:
https://plus.google.com/u/0/109039914818614234734/posts/773SfUEH4RJ
https://plus.google.com/113470488863620045551/posts/GSrZYcYpkHD

Il test è stato eseguito su un sito di prova con caricato uno starter template per WordPress che sto sviluppando scaricabile gratuitamente, i file attualmente usati da questo template sono rispettivamente tre js (jquery.js, bootstrap.js e un piccolo file per attivare la slide in home home.js) e tre css (style.css [vuoto], bootstrap.css e custom.css), la pagina su cui sono stati eseguiti i test è la home in cui è presente uno slider con diverse immagini, questo per rendere il test abbastanza verosimile con un sito in produzione.

Il sito è su hosting condiviso giusto per avere un banco di lavoro comune a moltissimi altri in circolazione – purtroppo il server non è il massimo che si può avere ma si difende ;-).

Cominciamo, come posso rendere asincrono jQuery su WordPress?

In questo articolo ti mostro alcuni metodi che ho sperimentato e possono essere utilizzati per rendere asincrono jquery e relative dipendenze su WordPress e anche alcuni trucchi per mettere in parallelo il caricamento dei file js e css, ma prima di procedere è fondamentale comprendere il meccanismo che utilizza wp per gestire questi file.

Le funzioni WordPress per gestire i JS
Il cms utilizza delle funzioni particolari.

WordPress mette a disposizione alcune funzioni che devono (o dovrebbero ;-)) essere usate per caricare i file javascript, dico devono perché sono importanti (come spiegavo prima) per evitare conflitti con altri js caricati per esempio dai plugin utilizzati e per mantenere il corretto caricamento delle dipendenze, per esempio i plugin js che dipendono da jquery ovviamente per funzionare correttamente devono essere caricati dopo jquery altrimenti non funzionerebbero, questo è possibile farlo grazie a due funzioni native di wp, per l’esattezza wp_register_script() e wp_enqueue_script() le quali grazie ad alcuni parametri che possiamo passargli ci danno anche la possibilità di caricare i nostri file js direttamente nel template sia fra i tag head che prima della chiusura del tag body, vediamo in dettaglio:

<?php wp_register_script( $handle, $src, $deps, $ver, $in_footer );?>
<?php wp_enqueue_script( $handle, $src, $deps, $ver, $in_footer );?>

Ecco una spiegazione dei parametri delle funzioni:

  • $handle: questo sarà il nome dello script (per esempio ‘jquery’)
  • $src: qui si dovrà mettere la url dello script, sia locale che da CDN
  • $deps: questo parametro è da utilizzare in caso lo script dipenda da altri, per esempio andrà inserito jquery nel caso appunto sia una sua dipendenza, in caso contrario si può inserire il valore NULL
  • $ver: qui si dovrà inserire la versione dello script altrimenti verrà pressa quella di WordPress installata, volendo si può inserire NULL
  • $in_footer: questo parametro invece darà la possibilità di poter caricare lo script o fra i tag head se “false” e prima della chiusura del tag body se “true”

Se usate insieme è necessario rispettare la seguente struttura

<?php
wp_register_script( $handle, $src, $deps, $ver, $in_footer );
wp_enqueue_script( $handle );
?>

dove in wp_register_script vanno passati tutti i parametri e in wp_enqueue_script solo il $handle; tutto questo andrà poi inserito in una funzione e agganciato all’hook wp_enqueue_scripts per poterlo poi caricare in wp_head (trovi comunque tutte le informazioni sulla pagina ufficiale del codex di WordPress).

Per gli script dentro l’installazione del template è possibile usare anche solo wp_enqueue_script e passargli tutti i parametri, nel caso invece di script su server esterni, per esempio da CDN, o per i plugin allora è fondamentale l’utilizzo di wp_register_script insieme a wp_enqueue_script nel modo indicato prima.

Ci sono altre due funzioni da conoscere che potranno tornare utili in certe situazioni che fanno l’opposto, ovvero “tolgono” dal caricamento gli script di cui non necessitiamo, queste sono wp_deregister_script() e wp_dequeue_script.

Lo stesso vale per il caricamento degli stili grazie a wp_register_style e wp_enqueue_style ma questi sono più limitati e consentono di caricare i CSS solo nell’header (poi vedrai perché).

Ovviamente nessuno ti impedisce di caricare i file js e css con il metodo “tradizionale” ovvero inserendoli a manina direttamente nel codice html della pagina e quindi usare jQl inserendo jquery e dipendenze al loro posto come ben spiegato da Maurizio. Se proprio vuoi provare ti consiglio di farlo in locale o su un sito di test, ricorda però che questo sistema è un po’ macchinoso (e secondo me anche non produttivo su wp) perché dovrai deregistrare eventuali js caricati da tema e plugin e quindi aggiungerli a jQl a mano, un lavoraccio insomma, però lo scopo di questo articolo è quello di usare gli strumenti forniti da questo cms e quindi proseguiamo con la guida.

Primo esperimento, proviamo con W3TC

W3 total cache

Esperimento 1
Asincronia con W3 Total Cache.

Il primo esperimento l’ho fatto con un plugin che utilizzo e che sicuramente conosci, W3 Total Cache; ho comunque voluto cercare sul repository ufficiale eventuali soluzioni alternative con plugin “più facili” da configurare anche per chi fosse poco esperto e volesse divertirsi in questa operazione, purtroppo però inizialmente la ricerca è stata vana, ho trovato e provato alcuni plugin ma nessuno che soddisfacesse quello che volevo ottenere (molti di questi poi non erano neppure aggiornati presentando fastidiosi errori php, almeno sulla versione 3.6 di wp che ho usato come test).

Ps: Nel caso ne conoscessi qualcuno che potrebbe fare al caso nostro segnalamelo pure nei commenti sotto 🙂

Il metodo che ho utilizzato con W3 Total Cache è stato quello di unificare e minificare i file js (anche quello inline) e quindi rendere asincrono il file risultante.

Premetto però che questo sistema ha si il vantaggio di rendere asincrono jquery e dipendenze (visto che verranno unificati seguendo la gerarchia impostata nel pannello amministrazione) ma sarà comunque una asincronia “finta” poiché sarà l’unico js presente nel documento HTML, ed essendo un file unificato sarà più pesante in dimensioni anche se il totale di Kb dell’intera pagina scaricata rimarrà invariato. Il lato positivo è che abbiamo ridotto le richieste HTTP.

W3 Total Cache è un plugin che non fa solo quello che spiegherò più avanti ma ti consente anche di poter ottimizzare molte altre caratteristiche del tuo sito – diciamo che questo fa parte della lista di plugin must have – e pur se non di facile utilizzo può dare molte soddisfazioni con una sua corretta configurazione.

Questo non è un metodo definitivo, ovvero, può capitare che qualche file per uno motivo o per l’altro non funzioni, per questo bisogna sempre sperimentare e trovare il giusto setup che ci consenta di avere comunque buone prestazioni.

Io cerco di evitare js che non mi consentono di poter ottimizzare le performance e quando mi capitano cerco alternative che non diano questi problemi.

Per cominciare dobbiamo prima di tutto sapere quali file js vengono caricati da WordPress e dove vengono caricati per il corretto funzionamento. Per vedere tutti i file caricati devi visualizzare l’html della pagina, con firefox per esempio puoi usare i tasti “ctrl u” (senza virgolette) quindi cercare i file .js all’inteno della pagina, compilare la tua lista e attivare nel pannello amministratore del plugin la sezione “Minify”, che si trova nelle impostazioni genereali del plugin (menù a sinistra):

Immagine menù W3TC

Cerca la tab “Minify” e (come mostrato nella figura sotto) metti la spunta su “Enable” (1) quindi su “Manual” (2) e quindi clicca su salva (3)

Attivazione minify su W3TC

Ora clicca su minify nel menù a sinistra:

Minify Menù W3TC

Ora spostati sulla tab JS (vedi figura sotto), metti la spunta su “Enable” (1), lascia la spunta su “Minify” (2), dovrebbe funzionare nella maggioranza dei casi, in alternativa potresti provare la sola combinazione, quindi nel menù a tendina sulla destra seleziona “Non-blocking using “async” “ (3), al punto (4) dovrebbe già essere selezionato il tema attivo, ora cliccando su “Add a script” (5) comincia ad inserire la url di ogni js cominciando da quella di jquery (6) (ti consiglio di provare con un file alla volta per evitare nel caso di problemi di dover togliere e reinserire tutti i file js).
Siccome seguiamo le regole base della WPO ovviamente caricheremo tutto nel footer e quindi nel menù a tendina a destra per ogni js seleziona “Embed before </body>” (7), volendo potresti anche decidere in quale file del template caricare il js (8) questo per evitare di portarsi dietro codice in tutto il sito quando effettivamente è usato solo in una pagina; quando hai caricato tutti i file clicca sul pulsante salva.

Configurazione minify su W3TC

Ora se tutto è andato per il verso giusto dovresti essere riuscito a rendere jquery e dipendenze “asincroni” :-).

Qui puoi vedere il test eseguito prima della cura e qui dopo la cura.

Però, (si, c’è un però, e ringrazio Andrea Pernici per le dritte che mi ha dato durante la scrittura di questo articolo) con questo sistema non abbiamo risolto definitivamente la questione. , abbiamo reso jquery asincrono ma alla fine il file viene accodato alle altre risorse durante il download (sistema non supportato da tutti i browser come puoi leggere qui: https://stackoverflow.com/questions/1834077/which-browsers-support-script-async-async ) e non messo in download parallelo, come mi ha fatto notare Andrea.

A questo punto potrebbe essere più conveniente usare l’attributo defer (cioè rimandare il download) sul file ottenuto piuttosto che l’async, sempre attivabile da W3TC, da evitare anche in caso si abbia molti js, si rischierebbe di creare un file troppo grosso aumentando così il tempo di caricamento totale e di rendering della pagina, cosa non bella per chi sta visitando il sito.

Secondo esperimento, ora usiamo Async JS and CSS

async js css

Esperimento 2
Asincronia con Async JS & CSS.

Quindi che si fa? Beh, si continua a sperimentare finché non si risolve il problema e la fortuna è stata che proprio in questi giorni mentre stavo scrivendo l’articolo è stato aggiornato uno dei plugin che avevo precedentemente provato (e che dava diversi errori come ho scritto sopra) scoprendo che ora che è stato fixato, questo plugin potrebbe essere una buona soluzione per rendere realmente non bloccante jquery e volendo anche i CSS (ma questo lo vedremo più avanti), il plugin si chiama semplicemente Async JS and CSS :-), e già la sua descrizione dice tutto:

“Converts render-blocking CSS and JS files into NON-render-blocking, improving performance of web page.”

Vediamo cosa fa esattamente. Quando si attiva possiamo accedere alla sua pagina di configurazione, semplice e intuitiva, poche funzioni ma essenziali:

Immagine del plugin Async Js and CSS

Come vedi dalla figura qui sopra i settaggi richiesti sono veramente pochi e intuitivi, in pratica, quando attivo, questo plugin legge dalla classe wp_scripts quali js e CSS vengono caricati, li prende e li va ad inserire nel footer all’interno di uno script che andrà a rendere asincroni i vari file rispettando le dipendenze varie. Per quanto rigurda i CSS abbiamo anche la possibilità di poter scegliere il metodo di reinclusione e testare quale sia il più performante per le nostre esigenze.

Ora cominciamo con il primo test di caricamento attivando la spunta su “Load Javascript asynchronously” – le due voci “Detect <script> tags in wp_head” e ” Detect <script> tags in wp_footer” servono per “prendere” eventuali script agganciati a quegli hook quindi se hai questa situazione metti pure la spunta anche su quelli altrimenti puoi anche non attivarli – e qui trovi il risultato del primo test eseguito; se tutto è andato correttamente ora jquery e dipendenze vengono caricati in modo asincrono senza problemi per lo slider e come vedi dalla waterfall due su tre file js vengono caricati quasi in parallelo tra loro.

Ora tocca ai file CSS, vediamo come possiamo ottimizzarne il caricamento

css

Non solo JS
Vediamo come ottenere il massimo.

Per quanto riguarda i CSS l’ideale sarebbe poterli caricare in parallelo con i file js durante il download della pagina, questo è possibile grazie alla caratteristica del browser di poter parallelizzare il download delle varie risorse di una pagina web. Ora sperimentiamo le varie opzioni del plugin e vediamo che succede.

Il primo test eseguito, che puoi vedere a questo indirizzo, ho messo la spunta su “Load CSS asynchronously” e lasciato attiva la prima voce di “CSS loading method” (Using <link rel=’stylesheet’ …> tags on the foot of document), andando a vedere il sorgente della pagina puoi notare che i vari file css vengono spostati alla fine del codice HTML, dopo i js e prima della chiusura del tag body, come vedi dai tempi di caricamento l’inizio render è migliorato parecchio e ora CSS e js sono praticamente in parallelo, a parte home.js.

Per il secondo test ho attivato la seconda voce “Using @import url(…) css rules on the foot of document” e qui puoi vedere il risultato, praticamente invariato rispetto al precedente, parallelizzazione di CSS e js e tempo di rendering quasi identici.

Per il terzo test ho attivato la voce “Creating <link rel=’stylesheet’ …> tags using javascript after document loaded”, che trovi qui, che in pratica include lo stile tramite javascript con l’effetto di ritardare il download dei fogli di stile quando è tutto caricato (in pratica effettua un defer della risorsa). Con questo metodo è migliorato leggermente l’inizio render, il documento completato e abbiamo anche ridotto le richieste HTTP di 2 unità, direi che ci siamo quasi :-).

Ora solo a titolo didattico qui trovi il test eseguito mettendo la spunta su “(default)Inserting all CSS styles inline into the document FOOTER” e qui invece quello relativo a “Inserting all CSS styles inline into the document HEADER”.

Caricare tutto lo stile all’interno dell’HTML non è la soluzione migliore poiché così facendo andiamo a aumentre le dimensioni della pagina aumentandone il tempo download (non le dimensioni dell’intero documento ma solo della pagiina html, in questo caso la index) proprio come accadeva precedentemente per il file js unico creato con W3TC.

Ultimo passaggio, risolviamo il FUOC

fuoc

FUOC
Che cosa è?

Adesso che abbiamo fatto i vari test e abbiamo trovato un buon compromesso di prestazioni abbiamo un altro problema. Come avrai potuto notare per qualche centesimo di secondo quando carichi la pagina, avendo spostato tutto il CSS nel footer dopo il JS, ovviamente viene caricato prima l’HTML senza stile e poi viene “disegnata” la pagina dopo che avrà caricato il foglio di stile. Questo problema è chiamato FUOC che è l’acronimo di Flash of unstyled content, l’istante in cui la pagina web appare senza stile. Anche se l’effetto dura veramente poco per chi ha una ADSL, per connessioni più lente come quelle di un cellulare potrebbe occupare tempi più lunghi e come puoi comprendere non è una bella cosa da vedere, quindi ora vediamo come risolvere questo problema.

Per evitare il FUOC dobbiamo inserire inline la parte di stile necessaria per poter “disegnare” il contenuto della pagina above the fold (ovvero nella parte visibile dello schermo, quella che vediamo quando carichiamo la pagina) all’interno dell’html fra i tag head. Ovviamente inseriremo solo quelle regole css utili per il painting iniziale ed evitare quel brutto effetto che hai potuto notare, a questo link qualche tempo fa il buon Andrea ha pubblicato un video dove viene spiegato come ottenere il css necessario utilizzando chrome e con questo file js da inserire negli strumenti per sviluppatori (ctrl+maiusc+i) seguendo i passi mostrati nel video è possibile ottenere lo stile necessario al painting della pagina.

Come dice lo stesso autore funziona abbastanza bene ma non è in grado di riconoscere le media queries e le pseudo-classi come :hover e funziona solo con i motori WebKit e Blink.

Il codice ottenuto andrà inserito inline all’interno del tag head proprio sotto il title in modo tale da farlo caricare prima possibile, in pratica dovrai ottenere una cosa del genere:

<head>
<title></title>
<style></style>
</head>

Ricorda anche che il css inserito inline dovrai toglierlo dal file principale altrimenti caricheresti inutilmente classi che sono già state caricate aumentando così la dimensione totale della pagina.

Purtroppo ho potuto notare che lo stile restituito da chrome non è “pronto all’uso” ma bisogna comunque metterci le mani e vedere se tutto funziona regolarmente. I miei esperimenti comunque sono in continuo svolgimento per trovare la soluzione migliore di codice da utilizzare inline, anche perché di pagine in un sito web non c’è solo la home :-).

Conclusioni

Bene, direi ormai di aver concluso il racconto della mia esperienza (che non è finita qui) e ora ti lascio ai tuoi test ricordandoti che se scopri incompatibilità con js vari oppure sei a conoscenza di altri sistemi per ottenere lo stesso risultato segnalalo qui sotto nei commenti così creiamo anche una lista che potrà tornare utile ad altre persone che vorranno divertirsi in questa avventura.

Prima di chiudere vorrei ringraziare Giorgio per questa opportunità e Andrea per avermi spinto a migliorare questo articolo :-).

Ciao
Enea

Sei membro del forum? Vuoi scrivere anche tu su SEO Blog gt
Chiedilo a @giorgiotave