WordPress et les JavaScripts asynchrones
Voici une optimisation simple à mettre en place et qui peut améliorer considérablement le temps de chargement de vos sites : différer le chargement des fichiers javascripts.
En règle générale, les javascripts sont synchrones, c’est à dire que lorsqu’une page web se charge et tombe sur une URL de fichier JS, le cacul de la page est suspendu, le temps de le télécharger.
On se retrouve donc sur certains sites WordPress avec une dizaine de librairies et de scripts qui viennent ralentir le chargement et l’affichage.
L’astuce dont je vais parler consiste à rendre tous les javascript appelés par WordPress « asynchrones » : Ils seront chargés parallèlement au reste de la page.
Cette méthode vous fera gagner en performance, donc en expérience utilisateur et potentiellement en référencement.
La librairie LabJS
Pour charger des javascripts de façon asynchrone, il faut utiliser une librairie de chargement de fichier JS.
LabJS en est une, comme il en existe d’autres, mais celle-ci pèse 640 bits avant gzippage.
Cela veut dire qu’au lieu de charger :
- jQuery
- deux ou trois librairies
- un ou plusieurs fichier JS
… pour parfois plusieurs centaines de Kbits au chargement de la page, votre site ce contentera de charger :
- un script de 640bits
- une simple instruction pour chaque autre script
Vos javascripts seront alors importés indépendamment du reste de la page.
Et là c’est comme les légumes : ça compte pas…
Mise en place
Pour appliquer cette astuce, la procédure est de modifier la variable de WordPress qui contient la file de javascript, avant que le CMS n’essaye d’imprimer les fichiers.
Nous allons prendre les infos qu’elle contient, et les insérer dans une autre variable globale qui nous servira plus tard, à afficher les scripts ajoutés à la queue, comme bon nous semble.
Écouter la variable globale $wp-scripts
La variable qui contient toutes les infos relatives au JS sur WordPress s’appelle $wp_scripts. Elle est un objet de la classe du même nom et WordPress l’utilise par le biais des fonctions regroupées dans le fichier functions.wp-scripts.php.
Avant toute chose, à l’init de WordPress, nous allons initialiser une variable $mes_scripts dans laquelle nous injecterons toutes les données qui nous intéressent.
Ensuite, avant que WordPress n’affiche les scripts, il faut que nous regardions le contenu du tableau queue de $wp_scripts.
Prenons ces infos et insérons-les dans notre variable perso.
Nous venons d’obtenir la liste des scripts mis à la file, tout au long du chargement de WordPress, ainsi que toutes les infos qui leur sont relatives…
Empêcher l’affichage normal des scripts
Pour empêcher que WordPress ne vienne lui-même imprimer les scripts, il suffit simplement de vider le tableau queue de l’objet $wp_script.
Dans le header et le footer, après avoir ajouté nos scripts dans $mes_scripts (donc avant de fermer la fonction je_veux_mes_scripts()), il faut ajouter le code suivant :
WordPress lorsqu’il exécutera wp_print_script(), ne verra aucun fichier dans la file, et ne fera rien du tout.
Gérer les dépendances des JavaScripts
Si à ce stade nous regardons notre variable globale, nous nous apercevront que les scripts sont bien dedans, mais chargés dans n’importe quel ordre.
Nous ne pouvons pas lancer le rendu du JS directement, il faut d’abord nous inquiéter des dépendances. Dans le cas on nous omettrions cette étape, nous risquerions d’obtenir de nombreuses erreurs de javascripts (et accessoirement le site ne fonctionnerai plus^^)
Et là on se dit :
Mais comment fait WordPress pour gérer ça ?
La technique employée par WordPress est de faire une boucle pour trier les scripts :
- Les scripts sans aucune dépendances sont chargés directement.
- Ceux qui ont besoin d’une dépendance déjà instanciée peuvent se charger
- Ceux qui attendent leur dépendances feront un deuxième tour (ou plus)
- Ceux qui requiert un script qui n’est pas dans la file feront aussi un autre tour, mais demandent l’instanciation des scripts dont ils dépendent
- Ceux qui ont des dépendances qui n’existent nul part crèvent en silence…
- Lorsque tous les cas sont traités, la boucle prend fin.
La méthode peut paraître bourrin au premier abord, mais en fait il n’y a pas vraiment de solution mieux adaptée.
Il faut créer une fonction, qui va être hookée sur wp_footer, dans laquelle nous allons trier les javascripts. C’est dans cette même fonction que nous rendront le JS par la suite. Elle doit être exécutée assez tardivement ; il faut lui attribuer une priorité assez élevée.
Les outils que nous allons utiliser sont :
- notre variable global $mes_scripts où sont stockés nos scripts
- la global $wp_scripts
- une variable temporaire $mes_scripts_ordonnes où nous allons stocker les javascripts, dans le bon ordre.
Au fur et a mesure de la boucle nous allons également avoir besoin de vider notre variable globale, il nous faut donc pour finir, une dernière variable $souvenir_de_mes_scripts qui sera une simple copie de $mes_scripts.
Pour commencer, les scripts sans dépendances sont ajoutés directement.
Ceux qui en ont font l’objet d’un traitement particulier, il ne seront ajoutés que si toutes leurs dépendances ont déjà été vues.
Lorsque la globale est vide, alors la boucle est rompue et tous les scripts sont ordonnés dans notre nouvelle variable.
Il ne reste plus qu’à appeler LabJS et lui indiquer les fichiers à charger.
Charger les scripts
Voilà, maintenant il est temps de tout afficher, à condition qu’il y ai des scripts, bien sûr !
Donc si $mes_scripts_ordonnes n’est pas vide, alors on ajoute la librairie LabJS, puis on ouvre une balise script.
Dans cette balise script il suffit de boucler sur $mes_scripts_ordonnes et pour chacun, afficher leurs datas (issues de wp_localize_script()) puis leur sources :
Le plugin WP Deferred Javascripts
Le code est complet et l’astuce devrait maintenant être opérationnelle, sauf dans certains cas :
- Si votre thème est codé un peu à l’arrache et que des scripts sont mis « en dur »
- Si des scripts sont mis en dur, avant wp_footer()
Si vous chargez des scripts dans le header, puis ajoutez des données qui lui sont relatives directement dans le template, via un wp_localize_script()
Ce bug a été corrigé dans la version 1.2 du plugin 🙂
Voici le code dans son intégralité :
Vu qu’il s’agit d’une optimisation assez avancé, l’intérêt n’est pas de recoder ça sur chaque site. Daniel Roch et moi en avons donc fait un plugin qui est disponible sur l’extend de WordPress : WP Deferred Javascripts (actuellement en version [baw_papii plugin= »wp-deferred-javascripts » info= »version » cache= »48″]).
Si vous avez quoi que ce soit comme soucis relatif au plugin, je vous invite à nous faire remonter les bugs via l’onglet « Support » de la page du plugin.
Alors, quel est maintenant votre ressenti sur le gain du temps de chargement lié à ce plugin ?
Merci pour ce premier plugin, d’autres prévus ? 😉
Sinon j’ai un autre plugin sur le feu depuis plus de deux ans… faudrait que je le termine… ;-P
: si tu trouves le plugin performant, n’hésite pas à faire une review ici.
: deux ans, tu es large encore ^^
En plus le chargement du Javascript prend pas mal de place pour mon site, et ça n’a pas l’air compliqué à mettre en place.
Thanks Willy & Daniel, c’est mon indice Google speed qui va être content 😉
Ps/ Willy, j’ai essayé ta 404…. une tuerie !!!
Par contre,je pense que ce plugin est plutôt dédié aux thèmes usine à gaz qui mettent 40 fichiers js dans le footer.
, Oui en mode Admin on se rend vite compte. Si en revanche on a un front bien optimisé avec un seul JS et un bon système de cache, je ne sais pas trop si on sent une différence.
Je suis content que la 404 te plaise ! Et encore elle n’est pas comme je l’aurais voulu…
Un jour mon plugin il sortira, un jour… (tu fais quoi vendredi en 8 ? Une petite coding night ?)
Si vous connaissez quelques sites bien optimisés par défaut, pour y faire un jsPerf avec et sans le plugin, je suis preneur !
j’ai installé votre plugin qui fonctionne fort bien mais depuis quelques jours j’ai changé de thème et maintenant j’ai un souci.C’est un thème responsive gratuit pour infos.Dans ce thème il y a un slider et si j’active le plugin celui-ci n’affiche plus les images,en désactivant le plugin , le slider re fonctionne?
Peut-être un conflit de scripts ? mauvais code css?
Auriez-vous une idée , une piste ?
merci
cordialement
sur mon site, votre plugin fait bugger les commentaires G+ avec ce plugin : Google+ Comments
très content de la première version avec une amélioration très net du temps de chargement , fonctionnnant bien avec minify.
Parcontre depuis les dernère mise à jour, j’ai constaté des ralentissements notoire au point que j’ai désactivé le plug in et décoché » Enable JavaScript Minification » dans minify pour que Lightview Plus puisse fonctionner.
voilà quelques détails , si cela peut vous aider…
Phil
Avec ce plugin, plus d’erreur. !
Chez moi cette extension empêche « Lightbox Plus Color » de fonctionner. J’aimagine que le javascript ne se charge pas correctement?
++ andre
Je viens de tester votre plugins mais je rencontre des soucis de javascript .
– Ubermenu ne semble pas aimer ( c’est pourtant un plugin très répendu )
– Ninja Popup ne s’affiche plus non plus.
Sinon le gain est énorme. Pourriez vous m’aider et me dire ce qui ne va pas sur mon site ?
merci et encore merci pour tous vos conseils
xavier
Bonjour, juste une question pour savoir si le plugin fonction toujours sur la dernière version de WP ? Car je ne vois aucune différence dans GT Metrix ou Pingdom. Merci