Publier devrait finir « en ligne », pas sur un webhook
Tous les CMS headless s'arrêtent à leur propre API et déclenchent un webhook. Ce qui se passe dans l'intervalle entre ce webhook et une page qu'un visiteur peut voir, et pourquoi personne ne s'en occupe.
Demandez à un CMS headless ce qui se passe quand un éditeur clique sur Publier, et vous obtenez une réponse précise : le statut de l’entrée change, le contenu devient disponible par l’API de diffusion, et un webhook part si vous en avez configuré un.
Demandez ce qui se passe ensuite, et la réponse devient floue, parce qu’ensuite n’est pas son problème.
Pour un site statique, « ensuite » représente toute la distance restante entre un clic et une page qu’un humain peut voir. Cet article parle de cet intervalle, de pourquoi il existe, et de ce qu’il coûte.
L’intervalle, étape par étape
Voici la chaîne réelle pour un site statique avec un CMS headless :
- L’éditeur clique sur Publier.
- Le CMS écrit la modification et la marque publiée.
- Le CMS envoie une requête HTTP à un hook de construction.
- L’hébergeur met une construction en file d’attente.
- La construction démarre, installe les dépendances, récupère le contenu, génère les pages.
- La construction réussit ou échoue.
- En cas de succès, l’hébergeur promeut le déploiement.
- Le CDN commence à servir la nouvelle version.
- Les caches expirent et la modification devient visible partout.
Le CMS possède les étapes 1 à 3. L’hébergeur possède les étapes 4 à 8. Personne ne possède le fait que l’éditeur attend, ni le fait de lui dire ce qui s’est passé.
Ce que vit l’éditeur, c’est : je clique, je vois une confirmation, puis rien. La confirmation signifie « l’étape 2 a eu lieu », qu’il lit raisonnablement comme « ma modification est sur le site ». Ce sont deux affirmations différentes, séparées par six étapes qui peuvent chacune échouer.
Les modes de panne que personne ne voit
La construction échoue. Une dépendance a publié une version cassée, un champ obligatoire s’est trouvé vide d’une façon que le gabarit n’avait pas prévue, l’hébergeur a eu dix mauvaises minutes. La construction passe au rouge. L’éditeur, lui, a lu « publié ». L’ancienne page continue d’être servie. Tout le monde croit le site à jour.
C’est celui qui coûte de l’argent. Un restaurant publie ses nouveaux prix le jeudi, la construction échoue, et il sert ses clients aux anciens prix tout le week-end parce que son site le dit.
Le hook n’a jamais été appelé. Les URL de webhook sont régénérées, les secrets tournent, quelqu’un supprime une intégration pendant un nettoyage. Désormais, Publier écrit dans une base et rien d’autre ne se produit jamais. Il n’y a pas d’erreur, parce que du point de vue du CMS tout a fonctionné.
La construction a réussi mais était derrière une autre. Deux éditeurs publient à une minute d’intervalle. Selon l’hébergeur, vous obtenez deux constructions, ou une construction annulée, ou deux constructions en course où la plus ancienne gagne. La modification du second éditeur disparaît sans erreur nulle part.
La construction a tourné avant que le contenu ne soit lisible. Le hook part à l’instant où l’écriture en base est validée. Si le contenu est servi par un cache ou une réplique de lecture, la construction peut démarrer et récupérer l’état précédent. La construction est verte, le déploiement est en ligne, et la modification n’y est pas. Celui-là est franchement pénible à diagnostiquer, parce que tout signale un succès.
Pourquoi les webhooks s’arrêtent là
Ce n’est pas un oubli : c’est une frontière qui a du sens pour l’éditeur du CMS.
Un CMS headless généraliste sert aussi des applications mobiles, des bornes et des sites rendus côté serveur. La plupart n’ont aucune construction à suivre. S’engager sur « nous vous dirons quand votre page est en ligne » suppose de comprendre votre hébergeur, de détenir un jeton pour lui, d’interroger son API et de gérer tous les modes de panne d’un système qu’il ne contrôle pas.
Ils s’arrêtent donc à la frontière de leur propre système, ce qui est une position d’ingénierie défendable et laisse un vrai trou pour qui construit des sites statiques.
Ce que suppose de combler cet intervalle
Le combler demande une poignée de choses peu spectaculaires.
Figer ce qu’on publie. Publier devrait produire un instantané immuable avec un identifiant stable, pas un pointeur sur un état mouvant. Sinon, une construction qui démarre à 14 h 31 et finit à 14 h 33 contiendra peut-être une modification faite à 14 h 32, ou pas, selon les caches. Avec un instantané figé, une construction donnée correspond à exactement un état de contenu, et revenir en arrière consiste à pointer un instantané antérieur.
Poser l’instantané ailleurs que chez soi. Si la construction lit votre API, votre panne devient celle de vos clients, au pire moment. Poser l’instantané sur un CDN fait qu’une construction aboutit même pendant que le CMS est éteint. Nous le vérifions en coupant notre API et en confirmant que le déploiement d’un client se termine.
Détenir des identifiants pour l’hébergeur. Déclencher une construction demande une URL de hook. Savoir si elle a réussi demande un jeton d’API. C’est un secret par site, qui doit être chiffré au repos, jamais réaffiché après saisie, et révocable.
Interroger, et renoncer. Demandez l’état du déploiement à l’hébergeur jusqu’à ce qu’il soit terminal ou qu’un délai expire. Une construction bloquée depuis quarante-cinq minutes est un échec, quoi qu’en dise l’hébergeur.
Regrouper et limiter. Deux publications dans la minute devraient produire une construction. Sans cela, un éditeur qui corrige trois fautes déclenche trois constructions, dont deux sont gaspillées et la troisième peut entrer en course.
Ouvrir le disjoncteur. Si une cible échoue à répétition, cessez de l’appeler et prévenez quelqu’un. Réessayer indéfiniment un hook cassé, c’est apprendre le problème par son client plutôt que par sa supervision.
Rapporter honnêtement. En cours, en ligne à telle heure, ou échoué avec une raison. Jamais une coche verte pour « nous avons écrit une ligne ».
Rien de tout cela n’est astucieux. C’est un fan-out avec suivi, réessais et disjoncteur, une ingénierie bien comprise. C’est simplement du travail situé entre deux produits, et donc en général fait par personne.
Ce que l’éditeur devrait voir
La conséquence sur l’interface est petite et mérite d’être dite, parce que c’est tout le propos.
L’éditeur clique sur Publier. Le bouton montre que la modification est en cours. Il devient « En ligne à 14 h 32 ». En cas d’échec, il le dit, avec quelque chose d’actionnable : réessayer, ou prévenir le développeur, avec un lien vers le journal de construction destiné au développeur plutôt qu’à lui.
Personne n’a à penser à vérifier le tableau de bord de l’hébergeur, parce que l’outil qui a dit « publier » est celui qui dit « en ligne ».
Le retour arrière, qui est le même problème à l’envers
Tout ce qui précède concerne la sortie d’une modification. La question miroir est de la reprendre, et c’est là que le modèle par instantanés se rentabilise une seconde fois.
Avec un état de contenu mouvant, revenir en arrière suppose de remettre le contenu comme il était, de mémoire ou depuis un historique de versions, puis de déclencher une nouvelle construction. C’est une reconstitution manuelle, qui prend autant de temps que la modification d’origine, et c’est exactement ce qu’on ne veut pas faire pendant qu’un client est au téléphone.
Avec des instantanés immuables, chaque publication est déjà un point de restauration. Revenir consiste à sélectionner un instantané antérieur et à reconstruire : l’état du contenu n’est pas reconstitué, il est réutilisé, octet pour octet. Deux clics, une construction, et le site est réellement revenu à ce qu’il était à 11 h 04 ce matin plutôt qu’à une approximation.
La contrainte que cela crée est la rétention, et autant l’expliciter parce que c’est une vraie limite. Les instantanés occupent du stockage, donc ils expirent : sept jours sur le plan gratuit, quatre-vingt-dix jours sur Site, un an sur Studio. Au-delà, l’instantané a disparu et revenir en arrière veut à nouveau dire éditer à la main.
Un comportement voisin mérite d’être connu, parce qu’il surprend : une image encore référencée par un instantané retenu ne peut pas être supprimée définitivement. Si un client essaie, on lui dit quel instantané la retient et jusqu’à quand. L’alternative, laisser passer la suppression, produirait un retour arrière qui restaure une page avec une image cassée, ce qui est pire que le désagrément.
Ce que nous abandonnons pour ça
Combler l’intervalle a des coûts, et ils sont réels.
La publication prend une à trois minutes au lieu d’être instantanée, parce qu’il y a réellement une construction. Nous montrons la progression plutôt que de faire semblant, mais c’est plus lent qu’un CMS rendu côté serveur où un enregistrement est immédiatement visible.
Nous détenons un identifiant par site. C’est une surface de sécurité : chiffré au repos avec une clé dédiée, jamais renvoyé par un point d’entrée après saisie, révocable à tout moment. Mais il existe, et un CMS qui se contente de déclencher un hook anonyme ne le porte pas.
Nous avons un avis sur les hébergeurs. Vercel, Netlify, Cloudflare Pages, GitHub Actions, ou un agent sur votre serveur. Quelque chose d’exotique passe par le hook générique, qui déclenche sans suivre, et vous revoilà dans l’ignorance.
Le regroupement introduit un petit délai. Les publications rapprochées sont fondues en une construction, donc le tout premier clic n’est pas toujours instantané.
La question à poser à n’importe quel CMS
S’il faut retenir une chose : quand vous évaluez un CMS pour un site statique, demandez ce que voit l’éditeur après avoir cliqué sur Publier.
Si la réponse est « une confirmation d’enregistrement », les six étapes restantes sont à votre charge, et votre client apprendra les pannes par ses propres clients.
Si la réponse contient les mots « en ligne » et une heure, quelqu’un a fait le travail ingrat.
Notre position sur le reste de l’architecture est dans comment nous gardons les sites statiques, et les comparatifs détaillent où chaque outil s’arrête.