Javascript à sa place

Chaque fois que je parle de reléguer les codes javascript en fin de page, je vois une moue sur le visage de mon interlocuteur. Mettre le javascript dans le <body> du document, et encore plus à la fin de celui-ci, et souvent préjugé comme une pratique « sale ». Laissez moi vous convaincre du contraire.

Un javascript pas sans conséquences

Le code javascript est exécuté par nos navigateurs dès qu’il est lu et téléchargé. Il peut modifier le flux de contenu courant (principalement avec document.write) et donc modifier totalement l’interprétation du reste de la page. Imaginez par exemple que votre script insère < juste devant div>.

Le résultat ne peut pas être prévu à l’avance ni vraiment effectué après coup. Si div> est déjà analysé le navigateur, l’ajout d’un chevron ouvrant ne pourrait plus transformer facilement ce texte en noeud DOM, puis changer toute la hiérarchie de noeuds DOM pour la brancher sur notre nouveau <div>. C’est trop tard.

Stoppez tout !

À cause de cela, le navigateur considère un script comme une ressource exclusive. Quand il rencontre une balise <script>, le reste de la page est mis en attente et l’analyse est stoppée le temps d’exécuter le script. L’interprétation du reste de la page reprendra quand le script sera téléchargé et que son exécution sera finie. Si le reste de votre page contient des images ou des composants externes, leur téléchargement sera retardé d’autant.

En insérant votre code javascript dans la balise <head>, ou en haut de votre document html, vous bloquez l’accès à la page. Pour un script de 50 ko, sur un débit réel de 2 mb/s et une latence de 40 ms, nous voilà à près de 250 ms auxquels il faudra encore ajouter le temps d’exécution du script. Votre navigateur vient d’arrêter tout l’analyse et le rendu de la page pendant un quart de seconde, pour un script de taille modeste. Imaginez si vous en avez plusieurs, ou qu’ils prennent un peu de temps à s’exécuter.

Quelle est votre priorité ?

Votre priorité c’est quoi ? la page elle-même et son contenu, ou vos ajouts javascript ? Si votre page est illisible sans javascript vous avez déjà définitivement un problème à la base, et il vous faut le corriger. Si votre javascript n’est qu’un ajout pour apporter un plus à l’utilisateur alors ne devrait-on pas privilégier l’affichage du contenu plutot que l’exécution du bonus javascript ?

Permettre d’insérer le code javascript à la fin du document, juste avant le </body>, c’est permettre à l’utilisateur de charger la page et d’initier tous les téléchargements nécessaires avant de bloquer le navigateur sur ce javascript. Cela prendra toujours un quart de seconde, mais pendant ce temps le visiteur voit la page chargée. 250 ms ce n’est rien mais c’est ça qui fait la différence entre une page qui apparait rapidement et une page qui met du temps à se charger.

Le cadeau bonus

Le point bonus c’est qu’à ce moment là vous savez que toute la page est analysée. Vous pouvez interagir avec tout votre DOM sans avoir à attendre le chargement complet de tous les composants ou à mettre en place des systèmes plus ou moins brillants pour détecter la fin de chargement de l’arbre DOM. Fini les ajouts d’événements et les bidouilles pour implémenter le DomContentLoaded en javascript.

Reste à savoir pourquoi vous trouvez ça « sale » de mettre le code javascript en fin du <body>. C’est tout à fait prévu et accepté dans les spécifications HTML, cela donne des résultats concrets et importants au niveau performance, et ça rend même votre code plus simple. Le seul argument objectif que je peux concevoir c’est si vous avez deux rendus différents pour la page : avec et sans javascript. Mais il y a une astuce plus que simple pour ceci, ce sera l’occasion d’un autre billet.

Safari

Il est intéressant de noter que les développeurs de Safari ont trouvé une solution partielle à ce problème dans leur dernière version de développement. Quand un script est exécuté, le reste de la page est envoyé à un second moteur d’analyse, annexe. Ce dernier se contente de repérer les ressources à télécharger par la suite et lance le téléchargement en parallèle. Leur moteur privilégie aussi les scripts quand plusieurs téléchargements sont en file d’attente.

Cela ne résout pas l’affichage qui reste bloqué en attendant le script, par contre on évite beaucoup de problème de latence réseau et on améliore la parallélisation des téléchargements. Au final, on peut s’attendre à un gain de performance significatif sur les pages avec plusieurs composants javascript. chargés en haut de page.

Publié par edaspet

Plus d'informations sur mon profil en ligne

6 réponses sur « Javascript à sa place »

  1. Ping : Éric
  2. Je ne suis pas non plus très d’accord avec « Le cadeau bonus ». Je me suis déjà trouvé dans une situation où il fallait tout de même ajouté un évènement malgré le script en dernière ligne.

    C’était une très petite page qui donnait le focus au champ principal. Sans évènement, le champ semblait sélectionné dans Safari mais le curseur n’était pas positionné dedans.

  3. Personnellement je n’ai pas croisé de problème de ce côté, mais ce n’est qu’un cadeau bonus. Si tu préfères garder une gestion de DomContentLoaded ou un simple setTimeout(…,0) pour palier les bugs d’un navigateur, c’est acceptable.

    Le vrai gain il est surtout là parce que le js est téléchargé et exécuté en fin de page.

  4. @Bruno : Plutôt que jQuery en entier, tu peux utiliser une simple fonction de 10 lignes environ. Comme ça tu perds pas le bénéfice de cette astuce en téléchargeant une lib bien trop lourde.

Les commentaires sont fermés.