Logo Jamstatic
Jamstatic
Sites statiques et architectures découplées
Frank Taillandier (traducteur·trice)

Comparaison des temps de compilation des générateurs de site statique

· Lecture 13 min · Performance, Eleventy, Jekyll, Hugo, Gatsby

Source : Comparing Static Site Generator Build Times par Sean C Davis.

Il y a tant de générateurs de sites statiques (SSG). C'est fatiguant de devoir décider par où commencer. Bien qu'une abondance d'articles utiles puisse aider à se repérer dans les options (populaires), ils ne facilitent pas la décision comme par magie.

Je me suis efforcé de faciliter cette décision. Un de mes collègues a construit une fiche d'évaluation du générateur de site statique. Elle donne un très bon aperçu de nombreux choix de SSG populaires. Ce qui manque, c'est la façon dont ils fonctionnent réellement dans la pratique.

Comparatif des principaux générateurs
Comparatif des principaux générateurs

Tous les générateurs de sites statiques ont en commun le fait qu'ils prennent des données en entrée, les font passer par un moteur de template et produisent des fichiers HTML. Nous appelons généralement ce processus « la compilation ».

Il y a trop de nuances, de contexte et de paramètres à considérer pour pouvoir comparer les performances des différents générateurs pendant le processus de compilation pour les afficher sur une feuille de calcul - et c'est ainsi que commence notre test de comparaison des temps de compilation des générateurs de sites statiques les plus courants.

Il ne s'agit pas seulement de déterminer quel générateur est le plus rapide. Hugo a déjà cette réputation. Je veux dire, ils l'écrivent sur leur site web - Le framework le plus rapide au monde pour le développement de sites web - donc ça doit être vrai !

Il s'agit d'une comparaison des temps de compilation de plusieurs SSG populaires et, plus important encore, d'analyser en détail ces temps de compilation. Choisir aveuglément le plus rapide ou discréditer le plus lent serait une erreur. Voyons ensemble pourquoi.

Les tests

Le processus de test est conçu pour démarrer de manière simple - avec seulement quelques générateurs populaires et un format de données simple. Une base sur laquelle on pourra s'appuyer pour tester d'autres générateurs et affiner les données. Pour le moment, le test comprend six des générateurs les plus populaires :

Chaque test utilise l'approche et les conditions suivantes :

  • La source de données pour chaque génération est constituée de fichiers Markdown avec un titre front matter et un corps de texte (contenant trois paragraphes de contenu) générés de manière aléatoire.
  • Le contenu ne contient pas d'images.
  • Les tests sont exécutés en série sur une seule machine, ce qui rend les valeurs réelles moins pertinentes que la comparaison relative entre les lots.
  • La sortie est un texte en clair sur une page HTML, exécutée par le starter par défaut, en suivant le guide de démarrage respectif de chaque générateur.
  • Chaque test est un essai à froid. Les caches sont effacés et les fichiers Markdown sont régénérés pour chaque test.

Ces tests sont considérés comme des tests de référence. Ils utilisent des fichiers Markdown de base et produisent du HTML non stylisé dans la sortie intégrée.

En d'autres termes, le résultat est techniquement un site web qui pourrait être déployé pour la production, bien que ce ne soit pas vraiment un scénario de la vraie vie. Cependant, cela permet une première comparaison entre ces frameworks. Les choix que vous faites en tant que développeur utilisant l'un de ces frameworks impacteront les temps de compilation de différentes manières (généralement en les ralentissant).

Par exemple, contrairement au monde réel, nous testons des générations à froid. Dans la vraie vie, si vous avez 10 000 fichiers Markdown comme source de données et que vous utilisez Gatsby, vous allez utiliser le cache de Gatsby, ce qui réduira considérablement les temps de génération (jusqu'à près de la moitié).

On peut en dire autant des générations incrémentielles, qui sont liées à des passages à chaud par rapport aux passages à froid, dans la mesure où elles ne génèrent que les fichiers qui ont changé. Pour le moment, nous ne testons pas l'approche incrémentale dans ces tests.

Les deux types de générateurs de sites statiques

Avant cela, considérons d'abord qu'il existe en réalité deux types de générateurs de sites statiques. Appelons-les basique et avancé.

  • Les générateurs de base (qui ne sont pas basiques sous le capot) sont essentiellement une interface en ligne de commande (CLI) qui prend des données en entrée et produit du HTML, et peut souvent être étendue pour traiter divers ressources (ce que nous ne faisons pas ici).
  • Les générateurs avancés offrent quelque chose en plus de la sortie d'un site statique, comme le rendu côté serveur, des fonctions serverless et l'intégration d'un framework. Ils ont tendance à être configurés pour être plus dynamiques par défaut.

J'en ai délibérément choisi trois de chaque type dans ce test. Les trois premiers à tomber dans le panier de base sont Eleventy, Hugo et Jekyll. Les trois autres sont basés sur un framework frontend et sont livrés avec des quantités d'outils variés. Gatsby et Next sont bâtis sur React, tandis que Nuxt est construit par dessus Vue.

Générateurs Basiques Générateurs Avancés
Eleventy Gatsby
Hugo Next
Jekyll Nuxt

Mon hypothèse

Appliquons la méthode scientifique à cette approche car la science est amusante (et utile) !

Mon hypothèse est que si un générateur est avancé, alors il fonctionnera moins vite qu'un générateurs de base. Je pense que les résultats en témoigneront, car les générateurs avancés ont davantage de coûts fonctionnels que les générateurs de base. Ainsi, il est probable que nous voyons les deux groupes de générateurs - de base et avancés - regroupés ensemble, dans les résultats avec des générateurs de base se déplaçant beaucoup plus rapidement.

Permettez-moi de développer un peu plus cette hypothèse.

Linéaire et rapide

Hugo et Eleventy domineront les tests avec des volumes de données plus petits. Ce sont des processus (relativement) simples dans Go et Node.js, respectivement, et leur temps de génération devrait le refléter. Bien que les deux générateurs soient moins rapides au fur et à mesure que le nombre de fichiers augmente, je m'attends à ce qu'ils restent en tête, bien que Eleventy soit peut-être un peu moins linéaire à l'échelle, simplement parce que Go a tendance à être plus performant que Node.

Lent, puis rapide, mais toujours lent

Les générateurs avancés, ou liés à un framework, démarreront et sembleront lents. Je soupçonne qu'un test sur fichier unique contient une différence significative - des millisecondes pour les tests de base, contre plusieurs secondes pour Gatsby, Next et Nuxt.

Les générateurs basés sur un framework font chacun appel à webpack pour la génération, ce qui entraîne une quantité importante de frais fonctionnels, quelle que soit la quantité de contenu qu'ils traitent. C'est le contrat tacite que nous passons en utilisant ces outils (nous y reviendrons plus tard).

Mais, à mesure que nous ajouterons des milliers de fichiers, je pense que nous verrons l'écart entre les deux catégories se réduire, même si le groupe avancé restera plus loin derrière d'une manière significative.

Dans le groupe des générateurs avancés, je m'attends à ce que Gatsby soit le plus rapide, uniquement parce qu'il n'a pas de composant côté serveur dont il faut se soucier - mais c'est juste une intuition. Next et Nuxt ont peut-être optimisé cela au point que, si nous n'utilisons pas cette fonctionnalité, cela n'affectera pas les temps de génération. Et je pense que Nuxt battra Next, uniquement parce que Vue a un peu moins d'impact que React.

Jekyll : le vilain petit canard

Ruby est tristement célèbre pour sa lenteur. Il est devenu plus performant avec le temps, mais je ne m'attends pas à ce qu'il rivalise avec Node, et certainement pas avec Go. Et pourtant, dans le même temps, il n'a pas le bagage d'un framework.

Au début, je pense que nous verrons Jekyll comme étant assez rapide, peut-être même impossible à distinguer de Eleventy. Mais au fur et à mesure que nous arriverons aux milliers de fichiers, la performance en prendra un coup. Mon sentiment est qu'il peut y avoir un moment où Jekyll devient le plus lent des six. Nous allons pousser jusqu'à la barre des 100 000 pour en être sûrs.

Les résultats auxquels on pourrait s'attendre, Hugo le plus rapide et Next.js le plus lent
Les résultats auxquels on pourrait s'attendre, Hugo le plus rapide et Next.js le plus lent

Les résultats sont arrivés

Le code de ces tests se trouve sur GitHub. Il y a aussi un site qui montre les résultats relatifs.

Après de nombreuses itérations pour établir les bases sur lesquelles ces tests pourraient être effectués, j'ai fini par réaliser une série de 10 tests dans trois ensembles de données différents :

  • Basique : Un seul fichier, pour comparer les temps de génération de base
  • Petits sites : De 1 à 1024 fichiers, en doublant le nombre de fichiers à chaque fois (pour faciliter la détermination de l'échelle linéaire des générateurs)
  • Grands sites : De 1 000 à 64 000 fichiers, en doublant le nombre de fichiers à chaque passage. Au départ, je voulais aller jusqu'à 128 000 fichiers, mais j'ai rencontré des problèmes avec certains des frameworks. 64 000 ont fini par suffire pour donner une idée de la manière dont les différents acteurs allaient évoluer avec des sites toujours plus importants.
Performance de base, Hugo est largement vainqueur
Performance de base, Hugo est largement vainqueur
Génération sur des petits sites (< 1024 fichiers) : Hugo est de loin le plus rapide, Gatsby devient plus lent dès 128 fichiers
Génération sur des petits sites (< 1024 fichiers) : Hugo est de loin le plus rapide, Gatsby devient plus lent dès 128 fichiers
Génération de gros sites (entre 1000 et 64000 fichiers): Hugo est de loin le plus rapide, Gatsby est exponentiellement plus lent
Génération de gros sites (entre 1000 et 64000 fichiers): Hugo est de loin le plus rapide, Gatsby est exponentiellement plus lent

Synthèse des résultats

Certains résultats m'ont surpris, alors que d'autres étaient prévisibles. Voici les points les plus importants :

  • Comme prévu, Hugo est le plus rapide, quelle que soit la taille du site. Ce à quoi je ne m'attendais pas, c'est qu'il loin devant tous les autres générateurs, même sur une génération de base (il n'est pas non plus linéaire, mais nous reviendrons sur ce point.)
  • Les groupes de générateurs de base et avancés sont assez évidents quand on regarde les résultats pour les petits sites. C'était prévu, mais il était surprenant de voir que Next est plus rapide que Jekyll avec 32 000 fichiers, et plus rapide que Eleventy et Jekyll avec 64 000 fichiers. Il est également surprenant que Jekyll soit plus rapide que Eleventy avec 64 000 fichiers.
  • Aucun des générateurs ne suit une échelle linéaire. Next.js est celui qui s'en rapproche le plus cependant. Hugo donne l'apparence d'être linéaire, mais c'est seulement parce qu'il est beaucoup plus rapide que les autres.
  • Je pensais Gatsby serait le plus rapide parmi les générateurs avancés, et je me suis dit que c'était celui qui se rapprocherait le plus des générateurs de base. Mais Gatsby s'est avéré être le plus lent, produisant la courbe la plus exponentielle.
  • Bien que cela ne soit pas spécifiquement mentionné dans l'hypothèse de départ, l'échelle des différences était plus grande que je ne l'aurais imaginé. Pour un seul fichier, Hugo est environ 170 fois plus rapide que Gatsby. Mais à 64 000 fichiers, il est plus proche - environ 25 fois plus rapide. Cela signifie que, si Hugo reste le plus rapide, il a en fait la forme de croissance exponentielle la plus spectaculaire parmi le lot. Il semble simplement linéaire à cause de l'échelle du graphique.

Qu'en conclure ?

Lorsque j'ai partagé mes résultats avec les créateurs et les mainteneurs de ces générateurs, j'ai généralement eu la même réponse. Pour paraphraser :

Les générateurs qui prennent plus de temps à générer en font davantage. Ils apportent plus aux développeurs, alors que les générateurs plus rapides (c'est-à-dire les outils "de base") concentrent leurs efforts en grande partie sur la conversion des modèles en fichiers HTML.

Nous sommes d'accord.

Pour résumer : La mise à l'échelle des sites Jamstack est difficile.

Les défis qui se présenteront à vous, développeur, au fur et à mesure que vous que la taille de votre site augmentera, varieront en fonction du site que vous essayez de construire. Ces données ne sont pas saisies ici car elles ne peuvent l'être - chaque projet est unique d'une certaine manière.

Ce qui compte vraiment, c'est votre niveau de tolérance à l'attente en échange de l'expérience de développement.

Par exemple, si vous allez générer un grand site à forte charge d'images avec Gatsby, vous allez le payer avec des délais de génération plus longs, mais on vous donne aussi un immense ensemble de plugins et une base sur laquelle construire un site solide, organisé et basé sur des composants. Faites de même avec Jekyll, et il vous faudra beaucoup plus d'efforts pour rester organisé et efficace tout au long du processus, même si vos générations peuvent être plus rapides.

Au boulot, je développe généralement des sites avec Gatsby (ou Next, selon le niveau d'interactivité dynamique requis). Nous avons travaillé avec le framework Gatsby pour construire un noyau sur lequel nous pouvons rapidement créer des sites web très personnalisés, riches en images, avec une abondance de composants. Nos temps de génération augementent au fur et à mesure que les sites se développent, mais c'est à ce moment que nous devenons créatifs en mettant en place des micro frontend, en déchargeant le traitement des images, en mettant en place des aperçus de contenu, ainsi que de nombreuses autres optimisations.

De mon côté, je préfère travailler avec Eleventy. En général, je ne fais qu'écrire du code, et mes besoins sont beaucoup plus simples. (J'aime me considérer comme un bon client pour moi-même.) J'ai le sentiment d'avoir plus de contrôle sur les fichiers en sortie, ce qui me permet d'obtenir plus facilement les performances de 💯 côté client, et c'est important pour moi.

En fin de compte, il ne s'agit pas seulement de ce qui est rapide ou lent. Il s'agit de savoir ce qui fonctionne le mieux pour vous et combien de temps vous êtes prêt à attendre.

Conclusion

Ce n'est que le début ! L'objectif de cet effort était de créer une base sur laquelle nous pouvons, ensemble, comparer les temps de génération relatifs des générateurs de sites statiques les plus populaires.

Quelles sont vos idées ? Quels sont les faiblesses du processus actuel ? Que pouvons-nous faire pour améliorer ces tests ? Comment pouvons-nous les rendre plus proches des scénarios du monde réel ? Devrions-nous transférer le traitement sur une machine dédiée ?

Voilà les questions auxquelles j'aimerais que vous m'aidiez à répondre. Parlons-en.