Logo Julien Wilhelm, Awebsome

30/04/2020

Chess / Vanilla JS : le comparatif

Public pour cette page :Développeur·se·s Front-End

Quand j'ai créé TextMatters, mon éditeur de texte autonome pour la publication de contenu rédactionnel en ligne, j'ai utilisé beaucoup de JavaScript pour en générer la structure. Il y avait tant d'éléments HTML à intégrer avec le langage, tant de briques à insérer les unes dans les autres, que j'avais mis au point un petit outil de rien du tout destiné à améliorer l'expérience de rédaction et de (re)lecture du script principal.

C'est de ce rien du tout dont je souhaite m'entretenir avec vous aujourd'hui.

Déclaration de la fonction Chess développée par Awebsome
Déclaration de la fonction Chess développée par Awebsome.

Chess n'est pas une énième bibliothèque.

Chess, dont l'acronyme signifie " Create HTML Elements Short Syntax ", est une fonction répondant à un usage unique ainsi défini : gagner en productivité et en lisibilité dans la déclaration et l'initialisation de ses éléments HTML avec JavaScript. Ni plus ni moins. Ce qui est le propre de la sobriété qui m'anime en tant que développeur web écoresponsable.

Si l'enjeu de cet article est avant tout de vérifier - ou non - la supériorité de Chess sur le natif que je me plairai ici à nommer Vanilla JS, c'est aussi l'occasion de se questionner sur les outils que nous utilisons dans nos métiers pour alléger la charge de notre travail au quotidien. Les détails de la mise en oeuvre de Chess sont quant à eux abordés dans le README du dépôt GitHub du projet (en) que je vous invite à consulter.

Modèle utilisé pour l'évaluation

Pour comparer Chess et Vanilla JS, le mieux est encore de les mettre en concurrence à travers un cas concret.

Voici le bout de code HTML à générer sur lequel reposera l'évaluation des deux méthodes.

Le code HTML à reproduire dans le cadre du comparatif entre Chess et Vanilla JS
Le code HTML à reproduire dans le cadre du comparatif entre Chess et Vanilla JS.

Le conteneur principal est un <button> auquel est attaché un évènement déclenché par un clic de souris (ou tap, sur les devices tactiles). Il contient deux enfants directs (un titre <h4>, un paragraphe <p>) ainsi qu'un enfant indirect (un <span>, descendant de <p>). Certains éléments possèdent des attributs (id, classes), d'autres du contenu textuel.

Test n°1 : lisibilité du code source

Voici tout d'abord le code rédigé avec Vanilla JS pour générer le HTML introduit ci-dessus.

Du code JavaScript en Vanilla JS
Le code JavaScript natif mis en oeuvre.

On reconnait d'emblée certains défauts propres à Vanilla JS dans la procédure de déclaration et d'initialisation d'éléments HTML :

  • Une syntaxe verbeuse qui nous rappelle qu'il s'agit d'un langage dit de haut niveau.
  • D'insupportables répétitions pour accomplir des opérations similaires.
  • Une absence de relief dans la relation parent(s)/enfant(s) : difficile d'y visualiser les éléments imbriqués les uns dans les autres.

Voici maintenant l'exacte retranscription du code précédent avec la fonction Chess.

Du code JavaScript utilisant Chess
Le code JavaScript associé à la fonction Chess.

Voici les différences notables :

  • Le code apparait plus court, plus aéré, mais aussi plus esthétique. Ce qui le rend d'autant plus lisible.
  • Grâce à l'indentation logique de chaque imbrication, la structure HTML décrite est visuellement représentée.
  • Le fait de pouvoir déclarer x enfants à la volée depuis un parent sans devoir réitérer l'appel à la fonction offre un gain réel de productivité.
  • À moin de spécifier le contraire, aucune variable n'est créée en dehors de la fonction.

C'est plutôt un bon départ.

Test n°2 : vitesse d'exécution

Les évaluations suivantes sont réalisées avec le navigateur web Chrome et la méthode performance.now(). L'objectif : comparer à travers 10 itérations successives le temps nécessaire à Vanilla JS puis à Chess pour créer le HTML de la démonstration.

Les résultats sont à la fois prévisibles... et intéressants !

Note : la notation ms employée ci-après est le symbole de la milliseconde, dont l'unité est ici arrondie à trois chiffres après la virgule par souci de clarté.

Premier échantillon

  1. Chess l'emporte (≃ 0.385ms plus rapide que Vanilla JS).
  2. Vanilla JS l'emporte (≃ 0.095ms plus rapide que Chess).
  3. Vanilla JS l'emporte (≃ 0.020ms plus rapide que Chess).
  4. Vanilla JS l'emporte (≃ 0.015ms plus rapide que Chess).
  5. Vanilla JS l'emporte (≃ 0.020ms plus rapide que Chess).
  6. Vanilla JS l'emporte (≃ 0.010ms plus rapide que Chess).
  7. Chess l'emporte (≃ 0.015ms plus rapide que Vanilla JS).
  8. Vanilla JS l'emporte (≃ 0.040ms plus rapide que Chess).
  9. Vanilla JS l'emporte (≃ 0.025ms plus rapide que Chess).
  10. Chess l'emporte (≃ 0.020ms plus rapide que Vanilla JS).

Deuxième échantillon

  1. Chess l'emporte (≃ 0.230ms plus rapide que Vanilla JS).
  2. Vanilla JS l'emporte (≃ 0.010ms plus rapide que Chess).
  3. Vanilla JS l'emporte (≃ 0.055ms plus rapide que Chess).
  4. Vanilla JS l'emporte (≃ 0.030ms plus rapide que Chess).
  5. Vanilla JS l'emporte (≃ 0.030ms plus rapide que Chess).
  6. Chess l'emporte (≃ 0.005ms plus rapide que Vanilla JS).
  7. Chess l'emporte (≃ 0.005ms plus rapide que Vanilla JS).
  8. Égalité !
  9. Vanilla JS l'emporte (≃ 0.005ms plus rapide que Chess).
  10. Chess l'emporte (≃ 0.015ms plus rapide que Vanilla JS).

Qu'interpréter de ces chiffres ?

La plupart du temps - pas tout le temps -, Vanilla JS se montre plus efficient que Chess - ce qui semble logique -, cependant leurs performances respectives restent toujours très proches. C'est un bon point pour Chess, dont la sobriété du modèle (un usage = une réponse) est récompensée.

Voir le code source utilisé pour la mise en concurrence sur GitHub (en).

Test n°3 : longueur / poids du code minifié

Le premier test a donné gagnante Chess ; le second a placé Vanilla JS en position de force ; ce troisième et dernier comparatif devrait nous permettre de départager nos deux champions.

Après avoir soumis les deux codes à un outil de minification (suppression des espaces et saut de lignes inutiles, des commentaires, etc.), mesurer avec précision le nombre de caractères utiles à l'expression de chaque style devient un jeu d'enfant. Dans le cas qui nous intéresse aujourd'hui, le JavaScript produit pour la version Chess mesure 342 caractères / octets, contre 613 avec Vanilla JS, soit un gain d'environ 44% ! Un vrai plus côté bande passante et, pourquoi pas, côté UX, avec du contenu web que l'on peut espérer rendre accessible plus vite.

Bien sûr, pour que ce résultat soit tout à fait recevable, il faudrait y intégrer le poids de la fonction Chess. Je ne le fais pas ici, pour une raison très simple : si j'additionne la longueur du code Chess à celle de la fonction Chess, j'obtiens un chiffre supérieur à la longueur du code Vanilla JS. Chess n'est pas amortie sur ce seul exemple. Parce que, précisément, ce n'est qu'un exemple. Mais la fonction devient très vite rentable au sein d'un véritable script.

En moyenne, Chess requiert entre 40 à 50% de moins de code que Vanilla JS pour un même résultat.

Chess : plus fort que le natif ?

Je le reconnais : autant j'aime partager mon travail, autant j'emprunte peu aux autres, pour diverses raisons. L'une d'elles, c'est que la plupart des outils que nous utilisons pour nous faciliter la vie ont trop de revers à mon goût. Aussi formidables soient-ils, ils commettent tous la même erreur : à vouloir couvrir trop de cas d'usage, ils ne sont jamais que partiellement exploités par leurs utilisateurs.

Chess n'échappe pas à cette logique : le peu qu'il accomplit peut déjà être trop pour certains. Pris dans la même tourmente que ses pairs, il cumule avantages (test n°1 et test N°3) et inconvénients (test n°2). Fort heureusement, quand quelques fractions de millièmes de seconde sacrifiées de façon indicible à l'exécution permettent de réduire le poids d'un script en téléchargement, la question n'est plus tant de savoir s'il faut privilégier le confort de la machine ou celui du développeur.

Chess, sur Github (en)

On en discute ici ou ? Vous pouvez aussi partager cet article sur:

Linkedin