Dans ce cours nous allons voir comment fonctionne Gutenberg sous le capot et comprendre comment est géré l’enregistrement des données en base ainsi que l’aspect dynamique des blocs.
Sommaire du cours
Il est essentiel de bien comprendre ce qu’il se passe derrière l’éditeur pour créer sereinement des blocs, car vous allez voir que ça ne se passe pas forcément comme on pourrait l’imaginer !
Afin de nous en rendre compte par nous-même, nous allons rédiger un article avec Gutenberg : pour cet exemple je vais utiliser un bloc « paragraphe », « titre », « pullquote », et « bouton ».
On va maintenant afficher le code source HTML généré par nos blocs. En haut à droite vous avez un menu représenté par 3 petits points verticaux (à la mode Android), et en cliquant dessus vous allez pouvoir basculer en mode Code editor.
Vous apercevez désormais le code généré par Gutenberg, qui sera lui-même enregistré en base de données.
Voyons cela plus en détails. La première chose que l’on remarque c’est que chaque bloc est entouré par des commentaires HTML, contenant le nom du bloc, ou du moins son slug (son nom de code) :
Ce sont ces commentaires qui permettent de délimiter le code de chaque bloc. Ils sont très importants pour Gutenberg et on va voir pourquoi juste après.
Le préfixe wp:
indique que c’est un bloc natif de WordPress. Quand on créera nos blocs, on y mettra notre propre préfixe.
Parfois même, des données supplémentaires sont insérées dans ce commentaire, c’est le cas du bouton qui enregistre dans un objet JSON son alignement et sa couleur :
Quelle idée ! Je peux avouer que ça en a dérouté plus d’un, et créé des débats. Après tout le HTML et surtout ses commentaires ne sont pas l’endroit idéal pour enregistrer des données non ? Je vous explique les raisons qui ont mené à ce choix un tout petit peu plus loin dans ce cours.
Rassurez-vous, ces commentaires n’apparaitront pas sur votre site car ils seront filtrés lors du rendu de la page :
Ok ! On va maintenant voir comment tout cela est enregistré en base, et surtout pourquoi ce choix contre-intuitif, mais avant tout, un dernier conseil :
Comment sont enregistrées les données en base ?
On va maintenant aller voir à quoi ressemble le contenu enregistré en base de données. Pour cela lancez votre base via PHPMyAdmin ou mieux, si vous êtes sur Local il suffit d’aller dans l’onglet Database et choisir Adminer ou Sequel Pro (qui est gratuit et que je vous conseille si vous avez un Mac).
Les articles sont enregistrés dans la table wp_posts
(ça n’a pas changé avec Gutenberg). Je vais prendre l’id le plus récent et regarder son contenu. Vous noterez qu’il y a plusieurs occurrences de mon article, ce sont les sauvegardes automatiques, le bon article est celui dont la colonne post_status
indique published
.
On voit bien que c’est exactement le même HTML que celui qu’on vient de voir dans l’éditeur qui est enregistré dans la base de données.
Vous vous demandez peut-être à ce point pourquoi ne pas enregistrer des données en JSON comme le ferait toute app React plutôt qu’en HTML ? Ca aurait plus de sens après tout, non ?
Ou peut-être garder une version HTML et une version JSON ? Cela a été considéré mais c’est problématique : on aurait alors 2 sources distinctes de données. En programmation on a besoin de n’avoir qu’une seule source de vérité. C’est un concept essentiel.
Mais alors pourquoi ne pas avoir opté pour le JSON ? Tout simplement pour une question de rétrocompatibilité : le code fourni en HTML resterait affiché sur un site sans Gutenberg, ou pourrait être interprété par un autre éditeur, par exemple un page builder.
En soi c’est logique : la fonction the_content()
de WordPress a toujours su afficher du HTML sans traitement derrière. C’était donc normal que ça continue de cette manière.
Mais du coup comment Gutenberg va pouvoir comprendre ce HTML brut la prochaine fois qu’on ouvre l’éditeur et transformer ça à nouveau en blocs dynamiques et personnalisables ? Pour répondre à cette question on va jeter un oeil au cycle de vie de Gutenberg.
Cycle de vie de Gutenberg et de ses données
La documentation de Gutenberg offre ce schéma qui explique plus en détails le cycle de vie des données et des composants :
De l’état à l’enregistrement (cycle de gauche)
On part du milieu avec le Post State : quand vous éditez un article, Gutenberg garde en mémoire les blocs affichés dans l’éditeur, leurs données, et les blocs disponibles à l’ajout. Ici on raisonne en tant que données pures.
Lors d’un enregistrement, les données sont sérialisées (= transformées) via la fonction JS wp.blocks.serialize()
pour être transformées en HTML, comme on l’a vu plus haut, puis enregistrées en base de données.
C’est ce HTML qui est la source de vérité : c’est-à-dire la donnée de référence pour Gutenberg (et la seule donnée enregistrée). Il n’y en n’a pas d’autre, c’est pour cela que certaines données sont enregistrées sous forme de JSON dans le commentaire HTML.
Lorsque l’on retourne modifier l’article plus tard, Gutenberg récupère le HTML de la base et va le parser via la fonction wp.blocks.parse()
: il va interpréter le HTML pour le convertir à nouveaux en blocs modifiables. Ca redevient des données JS traitées en React et stockées le temps de l’édition dans le Post State.
De l’état au rendu du bloc (cycle de droite)
On part maintenant de l’autre côté du schéma. Chaque bloc, qui est un composant React, recevra les données nécessaires et générera le rendu dans l’éditeur. C’est le rôle de la Block API.
C’est d’ailleurs cette partie qui est importante dans cette formation : elle nous permet de créer nos propres blocs et comme on va bientôt le voir, avec toute sa logique et ses paramètres.
Au bout du cycle on a donc l’éditeur visuel, qui affiche le rendu de chaque composant, ainsi que les barres d’outils et tout ce que vous pouvez voir à l’écran. C’est un véritable ballet de données temps réel qui transitent entre chaque composant.
C’est pour ça que je monte un peu en pression quand j’entend quelqu’un dire que Gutenberg est nul, alors qu’il ignore complètement le travail d’orfèvre qu’il a fallu pour faire fonctionner tout cela ensemble.
Et enfin la partie Editing intervient quand on modifie le bloc, les nouvelles données (le texte que vous êtes en train de modifier par exemple) sont mises à jour en temps réel dans l’état de l’application, et nous voilà de retour au State.
J’espère que ce petit tour au coeur de Gutenberg vous a permis de mieux comprendre ses rouages ! C’est important d’avoir en tête une idée générale de ce fonctionnement lorsque vous créerez vos propres blocs et ça vous aidera à mieux conceptualiser votre code.
Pour en savoir plus sur le cycle de vie, vous pouvez lire le readme du package Editor dans le répertoire Github Gutenberg.
Le problème du changement de Markup
Le problème de cette source de vérité, c’est que lorsque l’on va modifier le code HTML généré par notre bloc, Gutenberg ne va pas comprendre et affichera une erreur :
C’est parce que votre bloc s’attend à recevoir la nouvelle version du HTML, et qu’en base c’est toujours l’ancienne qui est enregistrée.
Dans la console on verra même une erreur plus détaillée avec ce qu’a reçu de Gutenberg, et ce qu’il attendait :
C’est un message que l’on verra très souvent quand on créera nos blocs.
Pendant la phase de développement ce n’est pas grave, il suffit de supprimer le bloc et de le recréer. D’ailleurs les deux options proposées : éditer le HTML ou la conversion dans un autre bloc ne sont pas très utiles selon moi.
Mais lorsque vous aurez une extension opérationnelle et utilisée, vous ne pouvez pas prendre le risque de tout casser. Heureusement Gutenberg a mis en place une fonction de dépréciation des blocs pour corriger ça. On verra ça un peu plus tard dans la formation.
Petite précision : en fait changer le code d’un bloc ne le « casse » pas en front, il continuera de s’afficher correctement. C’est simplement en back que l’erreur s’affichera quand le code ne sera pas reconnu comme conforme.
Maintenant que vous avez une bonne compréhension des rouages de Gutenberg, on va aller voir le projet sur Github pour découvrir des composants React que l’on pourra réutiliser pour nous même.
Au passage cela nous permettra de voir comment est organisé le code source, ce qui est toujours très intéressant.
Fred - FLQ
Le 13 février 2024
Hyper intéressant tous ces concepts et le cycle de vie de Gut : ça permet de prendre du recul ! C’est clairement le genre d’article qui fait la qualité de la formation (et la différencie des autres).
J’avoue que quand j’ai vu le code source, je me suis dit que c’était presque aussi dégueu que des shortcodes à gogo ou le markup laissé par certains builders. ^^
Le choix de la rétrocompatibilité fait sens mais ne doit pas se faire aux dépends de la portabilité des données. Si j’ai bien suivi, c’est un des prochains gros chantiers de la roadmap : on verra comment ils vont gérer ça. Je vois bien notamment un export en json via un parser.
Maxime BJ
Le 13 février 2024
Oui c’est en effet très important de bien comprendre ce concept majeur de l’éditeur pour l’utiliser correctement, développer des blocs et des thèmes. Ce qu’il faut retenir, c’est que le code est nettoyé côté front et qu’il sert uniquement au parser en back pour transposer le HTML en données pour React. J’ai hâte de voir ce qu’ils vont proposer ensuite. J’avoue qu’une approche full JSON serait pas mal pour plus de simplicité ! Car impossible de modifier les « compositions » directement dans le HTML sans tout casser à cause de données parfois en double (dans le markup mais également dans le commentaire HTML du bloc).
Lorlor31
Le 27 juin 2024
Bravo pour la qualité de vos articles !
Tout est super bien expliqué tout en allant en profondeur dans les concepts.
Merci !