.

javascript

Comment optimiser votre code et votre JavaScript pour améliorer votre vitesse de chargement ? Voyons les différences entre les attributs synchrone, asynchrone et defer, et en quoi utiliser du JavaScript asynchrone à foison peut être contre-productif pour la vitesse et les performances de vos pages web.

JavaScript : les différences entre sync, async et defer

Dans un billet publié sur le Perf Calendar en 2016, Steve Souders détaille ces 3 attributs et explique pourquoi il préfère l'option defer à async, bien que dans les deux cas, s’ils ne bloquent pas le parser HTML, ils peuvent bloquer le rendu de la page. Voici le fonctionnement de chacune de ces méthodes.

Optimisation de la vitesse de chargement et des performances : Javascript Asynchrone

Pour aller plus loin, cet article détaille la façon dont une page se construit élément par élément, et explique pourquoi certains scripts sont bloqués par le parser (analyseur) HTML.

Sync, pour du JavaScript synchrone

Avec cet attribut, l'exécution de JavaScript est bloquante pour l'analyseur. Pourquoi ? Parce que lorsque le navigateur détecte un script dans le fichier qu'il analyse, il doit suspendre la construction du DOM, télécharger le script, céder la place à l'exécution JavaScript, et laisser le script s'exécuter avant de terminer la construction du DOM.

Cette méthode est utilisée par exemple pour les scripts d’A/B testing afin d’éviter l’effet de flickering.

Asyncpour du JavaScript asynchrone

Async est réputé non bloquant, mais nous allons voir que ce n’est pas totalement vrai.

Dans le cas du JavaScript asynchrone, le navigateur ne va pas interrompre l’analyse du code HTML, il télécharge le script en parallèle. Cependant, une fois le téléchargement achevé, il exécute immédiatement le script et bloque alors l’analyse de la suite du code HTML, l’exécution des autres scripts, ainsi que le rendu de la page.

Le problème que peut poser async est donc le suivant : l’exécution des scripts ne suit pas l’ordre du code, et selon la quantité de JavaScript à exécuter, cela peut bloquer le fil d’exécution principal (main thread) et donc dégrader le Time To Interactive. Il y a un impact potentiel pour l'expérience utilisateur.

Defer, pour repousser l’exécution du JavaScript

Avec l’attribut defer, le navigateur identifie le script, le télécharge, mais ne l’exécute qu’une fois que le contenu du code HTML est parcouru en entier. Dans ce cas de figure, l’ordre d’exécution des scripts est respecté et démarre après le DOM Interactive.

JavaScript asynchrone, ou la tentation d’empiler les scripts

Profitant de cette réputation (pourtant injustifiée) d’être non bloquant, l’attribut async a fleuri sur tous les sites, au point qu’on en oublierait presque qu’un navigateur n’a qu’un seul fil d’exécution principal se chargeant à la fois du parsing du HTML, des CSS, de l’exécution du JavaScript et du rendu de la page - et ce en plus des téléchargements qui peuvent se dérouler en tâche de fond. 

Ce phénomène est aussi renforcé par le fait que les temps de réponse serveur et de connexion sont de plus en plus courts, mais ce n’est pas une raison pour multiplier sans limite les scripts en utilisant un attribut async. Ça ne les rend pas gratuits en termes de performance web !

En effet, quand beaucoup de scripts asynchrones s’exécutent, si ce n’est pas bloquant pour le téléchargement, ça le reste pour l’exécution. Le principe est d’ailleurs très bien illustré par ce tableau publié par Addy Osmani qui récapitule la priorisation des scripts dans Chrome : les scripts asynchrones sont en bas, même quand ils sont prioritaires pour l’exécution.

Remettons l’église au milieu du village, soyons précis sur ce qu’on entend par “non bloquant” : cela concerne en réalité uniquement la stack réseau, et non le rendu de la page et l’interactivité.

Sachez que même un script asynchrone peut ainsi entraîner un SPOF, non pas au niveau du rendu de la page mais de l’exécution, mettant à mal l’interactivité de la page. Et si c’est un script tiers vous n’aurez évidemment pas la main dessus.

Alors, comme nous sommes bien conscients de l’utilité des scripts - qui plus est pour le marketing -, voici quelques bonnes pratiques pour vous aider à les utiliser en préservant vos performances :

  • découpez votre code pour éviter les long tasks (scripts qui mettent plus de 50ms à s’exécuter) qui bloquent le navigateur et dégradent votre Time To Interactive, et donc votre expérience utilisateur ;
  • fixez un budget performance et faites le ménage dans vos scripts ;
  • ne vous en remettez pas uniquement à un gestionnaire de tags, car cela ne vous aidera en rien pour l’exécution des scripts.

Enfin, si vous vous demandez plus précisément comment intégrer efficacement vos scripts et améliorer vos performances, Steve Souders aborde le sujet dans sa conférence “Make JavaScript Faster” à performance.now 2018 ; Flavio Copes en parle ici sur son blog ; et nos amis de Dareboost également.

Et pour optimiser automatiquement et durablement vos performances :

Découvrez nos fonctionnalités