Rant : Hugo et Tailwind

  1. Disclaimer
  2. Hugo
    1. Trois formats de configuration
    2. Rien n'est intuitif
    3. Un templating à gerber
    4. Quelques points positifs
  3. Tailwind
  4. C'était mieux avant
  5. Quels usages réels pour Hugo et Tailwind ?
  6. Mes choix techniques futurs

Si vous lisez mon blog de temps en temps, vous saurez que j'ai publié quelques articles concernant Hugo, le gestionnaire de sites statiques. En revanche, ce que seuls les plus attentifs auront remarqué, c'est que je suis passé à Tailwind CSS il y a près de trois ans, et que dans l'ensemble, j'en suis plutôt satisfait. Ou plutôt, j'en étais satisfait.

Disclaimer

Alors, oui, je vais pester sur Hugo, Go, Tailwind et Javascript. Oui, je suis un développeur PHP, et un connard de boomer (enfin je crois). Oui, je connais mieux les ficelles de PHP que de Go. Non, je ne suis pas officiellement un développeur frontend, mais j'ai un certain passif dans l'usage et la diffusion des standards du web (c'est d'ailleurs pour ça que le sujet me touche particulièrement). C'est dans le titre : je vais faire du rant. Si vous me connaissez, vous savez que je ne vais pas y aller avec le dos de la cuiller. Vous voilà prévenus.

Hugo

Comme son nom l'indique, Hugo est écrit en Go, ce qui présente certains avantages, mais aussi de lourds inconvénients qui commencent à sérieusement me gonfler au fil des jours. Les critiques que je vais formuler ici ne sont pas toutes dues au langage dans lequel Hugo est écrit, cependant.

Trois formats de configuration

JSON, YAML et TOML. Sérieux, choisissez-en un et foutez-nous la paix. Trop de choix tue le choix. C'est trop facile de faire un mauvais choix. Si tu paries sur le mauvais format et que les développeurs d'Hugo font le choix de supprimer son support, t'es bon pour réécrire toute ta configuration. Vous m'objecterez sans doute qu'il y a peu de chances pour que ça arrive : JSON est pratiquement universel de facto, yaml a le vent en poupe grâce à des poids lourds qui le mettent en avant (c'est pas pour autant que moi je le cautionne). Par contre, jamais entendu parlé de toml avant Hugo.

Le problème avec ce choix, c'est la portabilité. Si quelqu'un a fait le choix de toml alors que moi j'utilise json, et qu'il publie une configuration que j'ai envie de réutiliser, je dois la réécrire. C'est particulièrement pénible quand ça concerne les thèmes et leurs variables.

Rien n'est intuitif

La documentation de Hugo est imbitable. On ne sait pas quoi chercher ni où. Ça devrait être simple pourtant : configuration de base, 2-3 options de formatage, quelques fonctions pour les assets (CSS et Javascript), et on devrait être bons. Non : pour Hugo, la gestion des assets se fait dans des pipes. Comment tu peux savoir que tu dois chercher pipes quand tu veux minifier un CSS ou obtenir le hash d'un asset ?

Formater une date avec Hugo ? Pas de problème. Selon la documentation, si tu veux obtenir Friday, March 3, 2017, tu fais {{ .Date | time.Format "Monday, January 2, 2006" }}.

Pour les autres langues, au hasard le français, débrouilles-toi. Tu veux générer une datetime dans un format valide pour la mettre dans une balise <time> ? Si tu as trouvé comment faire, je veux bien l'info…

Le scoping des variables est un bordel sans nom. Impossible de passer des variables à un partial (parce qu'un partial, c'est mis en cache), l'usage du . pour tout et n'importe quoi est abominable, sans compter que parfois il faut utiliser $., à ce jour je n'ai toujours pas compris comment ça fonctionne.

Pour les dates et cette histoire de scope, ce n'est pas totalement Hugo qui est a blamer, c'est surtout Go. Ce qui m'amène au point suivant.

Un templating à gerber

Pas de notion d'héritage direct dans le HTML. Je peux bien définir un layout particulier pour une page ou une section, mais je ne peux pas définir un template qui hérite d'un autre. Le copier/coller peut-être évité par l'usage de partials, mais ce n'est pas toujours possible. Ça, couplé à l'absence de composants paramétrables (en gros, des partials auxquels on pourrait passer facilement des variables) rend l'usage des templates très pénible.

Surtout que la structure imposée par Hugo est, là encore, peu intuitive. Certains templates vont dans _layouts, d'autres à la racine du modèle, c'est le bordel. Encore une fois, rien que la documentation fout l'angoisse.

Ah, et, je n'ai jamais réussi à utiliser la pagination, toujours bloquée à 10 éléments, malgré la configuration qui va bien. Pas pour rien que vous ne trouverez aucune notion de pagination nulle part sur mon site, sans compter que je trouve ça parfaitement inutile dans le cas de mon blog personnel.

Il est possible d'utiliser des shortcodes dans son markdown. Pas mal, sauf que la syntaxe est spécifique à Hugo (Go, en vérité). Migrer vers une autre plateforme va être un enfer. Heureusement que je m'en sers avec parcimonie.

Je passe sous silence range, les if, bref, le templating dans Hugo, j'en ai ma claque. C'est laid, difficile à maintenir, pas intuitif.

Quelques points positifs

C'est loin d'être suffisant pour moi désormais, mais j'accorde quelques points positifs à Hugo.

En effet, c'est extrêmement rapide. En particulier pour l'optimisation des images.

Et, en effet, une fois que tout est bien configuré et qu'on n'y touche plus, ça fait l'affaire. Mais dès que tu veux trifouiller, améliorer, bidouiller, pousser un peu plus loin que ce qui est fourni par défaut, c'est franchement la merde.

Tailwind

Tailwind est un framework CSS qui a bonne presse ces derniers temps. À tel point que Laravel en a fait son framework par défaut pour tous les packages officiels disposant d'un frontend.

Le problème, c'est que Tailwind, c'est lourd. Très, très lourd.

Pendant des années, on a rabâché qu'il ne fallait pas mettre les styles inline dans les composants HTML, afin d'éviter de se retrouver avec des lignes du genre :

<div style="background-color: red; color: white; padding: 5px; border-radius: 10px; box-shadow: 1px 2px #aaa">
    Coucou
</div>

Tailwind nous propose donc de faire ceci :

<div class="bg-red-500 text-white p-5 rounded-lg shadow shadow-neutral-400">
    Coucou
</div>

Personnellement, je ne trouve pas ça tellement mieux, alors, naturellement, on se dit : "Bah, il suffit d'extraire ça dans un CSS !". Ok :

<div class="mon-composant">
    Coucou
</div>
.mon-composant {
    @apply bg-red-500 text-white p-5 rounded-lg shadow shadow-neutral-400;
}

Bon, ça créé une forte dépendance avec Tailwind dans le CSS (@apply est une directive fournie par Tailwind) en plus de le rendre dégueulasse, mais au moins ça supprime la dépendance au framework du HTML qui devient plus facile à maintenir.

Sauf que c'est découragé par Tailwind, qui suggère plutôt d'utiliser des composants HTML. Des composants dont on ne dispose pas dans Hugo. En fait, Tailwind nous suggère fortement de produire du HTML dégueulasse et pas de CSS custom. Ce qui m'amène à formuler une observation (que j'ai vu de mes yeux au boulot et ailleurs sur Internet) : les développeurs frontend aujourd'hui n'utilisent plus HTML et de moins en moins CSS.

C'est-à-dire que pour eux, HTML et CSS sont les produits finaux dont ils n'ont pas à se préoccuper parce que les frameworks font le boulot. Peu importe que le HTML produit soit dégueulasse, de toute façon on ne va jamais y mettre le nez. Ils ne vont plus dans la console du navigateur que pour voir du javascript. Le HTML/CSS est totalement opaque, inintéressant. Il n'existe déjà pratiquement plus aux yeux des développeurs frontend modernes qui ne voient que le javascript, un peu comme si un dev système s'en foutait du binaire produit du moment qu'il tourne. Et le HTML/CSS n'est pas leur affaire, c'est celle des web-designers.

Du coup, on se retrouve avec des frameworks frontend qui sont beaux par défaut (comme Tailwind), mais qui "obligent" à créer un code HTML/CSS immonde.

Si c'était que ça, à la limite, on peut se dire que c'est "l'évolution" des outils. Sauf qu'en plus, le CSS produit ne passe pas la validation du standard.

Tailwind est en plus assez éloquent sur son approche du développement. Mais les opinions de ses devs laissent parfois pantois :

The biggest maintainability concern when using a utility-first approach is managing commonly repeated utility combinations. This is easily solved by extracting components and partials, and using editor and language features like multi-cursor editing and simple loops.

Extraire dans des composants et des partials, je veux bien. C'est effectivement une bonne pratique. L'édition multi-ligne passe encore mais c'est quand même un peu du foutage de gueule. Mais par contre, des boucles simples ? Tu fais ça comment en pur HTML/CSS ? Tu peux pas : il faut du javascript. Non merci, pas pour mon blog perso.

C'était mieux avant

J'aime bien la faire, celle-là. Allez-y, sortez-moi vos meilleurs arguments : "Ouais, avant on se faisait chier, le CSS c'est de la merde, gnagnagna, maintenant les frameworks frontend font le café". Et téléchargent la moitié d'Internet pour styler deux composants.

Alors, moi je veux bien. Mais alors optimisez vos putains de CSS et de javascript. Me faites pas télécharger 25 fichiers différents parce que vous êtes pas foutus de concaténer vos assets. Utilisez la compression (gzip, voire brotli, soyons fous).

Bref. Du coup, Hugo et Tailwind me gonflent. Beaucoup de hype, alors qu'au final c'est pas génial. Pour mes cas d'usage en tout cas, c'est-à-dire le blog et mes projets persos et moins persos (comme Cyca qui avance très doucement, principalement à cause du frontend).

Quels usages réels pour Hugo et Tailwind ?

Pour Hugo, c'est top quand tu veux un blog vite fait avec un thème fourni par la communauté. Du coup, tu as une structure, une certaine rigidité pour ainsi dire, tu restes dans les clous du thème choisi et tu es tranquille. Mais c'est clairement pas fait pour quelqu'un comme moi qui aime bien bidouiller.

Pour Tailwind, c'est un peu plus subtil. Je ne peux pas être absolu et dire "c'est impossible à maintenir", surtout si je compare à du CSS vanilla. Tailwind m'a quand même permis de sortir une version utilisable de Cyca, et de faire un blog pas trop dégueulasse à consulter.

Surtout que l'approche de Tailwind n'est pas totalement mauvaise, mais j'échoue encore à voir l'intérêt par rapport à du CSS "classique".

Je dirai donc que Tailwind, c'est bien pour des projets relativement gros, où l'on utilise de toute façon un framework javascript en plus, de façon à tirer totalement profit des composants HTML et des styles associés. Typiquement, une application web au code source fermé, dont le frontend est totalement maîtrisé de A à Z. Pour un projet open-source, je pense que le problème majeur est un potentiel manque de cohérence visuelle entre différents composants. Et peu importe l'ouverture du code, on aura de toute façon un HTML ou un CSS bloaté (malgré le tree-shaking, technique de fégniasse). Je déteste devoir faire ce genre de choix.

Mes choix techniques futurs

Du coup, pour le blog, je me pose sérieusement la question de migrer vers autre chose que Hugo. Jigsaw me parle dans la mesure où c'est un environnement qui m'est familier (Laravel), j'y trouverai sans doute moins de choses à redire.

Remplacer Tailwind va demander plus de réflexion. Pour le blog, il est exclu d'utiliser un framework dépendant de javascript. Je m'en fous d'utiliser javascript pour développer mes pages, mais mon blog doit être parfaitement consultable sans javascript par défaut. À vrai dire, je songe fortement à me passer complètement de framework, et écrire du bon "vieux" CSS.

Il faut savoir que depuis quelques jours (2-3 semaines), je passe mon temps à refactorer le HTML et le CSS de ce blog, et ça commence à me gonfler. Esthétiquement, je trouve mon blog plaisant, mais au niveau du code, il y aurait mieux à faire (et surtout, qui passe la validation HTML et CSS).

Ça va être mon prochain cheval de bataille, d'autant que si je trouve quelque chose qui me plait, je l'utiliserai sûrement dans mes autres projets.

Plus d'informations