Formation « Développer des blocs Gutenberg sur mesure avec React »

Comprendre le cycle de vie de Gutenberg et de la Block API

Lecture : 9 minutes • 3

Dans ce cours nous allons voir comment fonctionne Gutenberg sous le capot afin de comprendre comment l’éditeur gère d’un côté l’enregistrement du contenu dans la base de données, et de l’autre comment il le réinterprète au chargement.

Avant de continuer avec la création de blocs sur mesure, je vous propose qu’on soulève le capot de WordPress afin de voir comment fonctionne Gutenberg.

Il y a notamment un concept majeur qui s’appelle le cycle de vie de Gutenberg.

Vous allez voir, c’est intéressant et ça permettra de bien comprendre les mécanismes en jeu.

Comment les données sont-elles enregistrées ?

On va commencer par revoir les bases et notamment la manière dont Gutenberg génère le HTML et l’enregistre en base.

Du côté de Gutenberg

On commence du côté de l’éditeur. Pour cela, nous allons rédiger un article : pour cet exemple je vais utiliser quelques blocs natifs.

verrouillé Vidéo premium

Cette vidéo est réservée aux détenteurs de l’offre premium.
Envie de nous rejoindre ?

Choisir une formule

Voici un exemple de contenu réalisé avec Gutenberg :

L'éditeur de blocs Gutenberg, avec un contenu type à l'intérieur : titre, paragraphe, citation, bouton.
Un contenu classique écrit avec l’éditeur de blocs

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, et en cliquant dessus vous allez pouvoir basculer en mode Code editor.

L'éditeur affiche la version générée en HTML du contenu écrit précédemment.
La version code du contenu écrit précédemment

Vous apercevez désormais le code généré par Gutenberg et qui va d’ailleurs être enregistré en base de données.

Conseil

Vous pouvez également utiliser le raccourci clavier Command+Option+Maj+M sur Mac ou Ctrl+alt+Maj+M sur Windows.

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 :

HTML

On observe un préfixe wp: qui est suivi du nom du bloc.

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.

Parfois même, on peut observer des données supplémentaires dans ce commentaire. C’est notamment le cas du bouton qui enregistre dans un objet JSON son alignement et sa couleur :

HTML

Dans le cours précédent, notre valeur booléenne hasTag était enregistrée de la même manière :

HTML

Quelle idée ! Je peux avouer que ça en a dérouté plus d’un, et créé des débats dans les premiers jours de Gutenberg.

Après tout, le HTML et surtout ses commentaires ne sont pas l’endroit idéal pour enregistrer des données.

Je vais vous expliquer les raisons qui ont mené à ce choix un tout petit peu plus loin dans ce cours.

Mais rassurez-vous, ces commentaires n’apparaîtront pas sur votre site car ils seront filtrés lors du rendu de la page. Voici le rendu en front, un HTML propre et sans fioritures :

HTML

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 :

À éviter

Modifier directement le contenu HTML ici pourrait casser vos blocs. Autant c’est quelque chose que l’on faisait avec TinyMCE, autant ici il ne vaut mieux pas s’amuser avec si on ne sait pas exactement ce que l’on fait.

Du côté de la base de données.

On va maintenant aller voir à quoi ressemble le contenu enregistré en base de données. Pour cela lancez votre base via Adminer à partir de LocalWP.

verrouillé Vidéo premium

Cette vidéo est réservée aux détenteurs de l’offre premium.
Envie de nous rejoindre ?

Choisir une formule

Il suffit d’aller dans l’onglet « Database » et cliquer sur « Open Adminer ».

Le logiciel LocalWP par WP Engine. Notre site est sélectionné à gauche. On y voit l'onglet Database et le lien pour ouvrir Adminer.
Accéder à la base de données depuis LocalWP

Les publications (pages, articles…) sont enregistrés dans la table wp_posts.

C’est quelque chose qui n’a pas changé avec Gutenberg. La structure de la base de données de WordPress est restée la même depuis la nuit des temps.

Je vais prendre l’id le plus récent et regarder son contenu. Vous noterez qu’il y a plusieurs occurrences de mon article : la plupart sont des sauvegardes automatiques de la publication.

Le bon article est celui dont la colonne post_type indique post et post_status indique published.

L'interface de Adminer qui montre le contenu de notre publication et notamment le HTML généré par Gutenberg.
On retrouve le HTML généré par Gutenberg dans la base

On voit bien que le HTML enregistré en base de données est exactement le même HTML que celui qu’on vient de voir dans l’éditeur.

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

Lorsque vous éditez le contenu d’une publication dans l’éditeur, il se passe plusieurs choses en coulisses.

verrouillé Vidéo premium

Cette vidéo est réservée aux détenteurs de l’offre premium.
Envie de nous rejoindre ?

Choisir une formule

La documentation du package editor de Gutenberg offre ce schéma qu’on va décortiquer et qui explique plus en détails le cycle de vie des données et des composants :

Schéma représentant le cycle de vie de Gutenberg : de la génération des données dans React à l'enregistrement du HTML en base de données.
Le cycle de vie de Gutenberg

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 (= des variables dans React).

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 dans la 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.

C’est à ce moment que Gutenberg va extraire les attributs du HTML à partir des instructions de notre block.json.

JSON
block.json

C’est là où notre sélecteur CSS et la source vont entrer en jeu !

Gutenberg stocke ensuite toutes ces données dans des variables React. C’est la représentation de l’état, sous forme de données brutes : retour au 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 visuel du bloc dans l’éditeur. C’est le rôle de la Block API.

Conseil

La Block API est le nom donné au mécanisme qui gère les blocs. C’est lui qui nous permet d’en déclarer de nouveaux sur-mesure.

C’est d’ailleurs cette API qui est importante dans cette formation : elle nous permet de créer nos propres blocs avec toute sa logique et ses paramètres. C’est de cette manière que Gutenberg envoie les attributs à nos composants via les props.

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.

Et enfin la partie Editing intervient quand on modifie ou insère un 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.

Si vous êtes curieux d’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 si le HTML du bloc change

Le problème de cette source de vérité, c’est que lorsque l’on va faire évoluer l’un de nos blocs, en modifiant le code HTML généré, Gutenberg ne va pas comprendre et affichera une erreur au prochain chargement.

verrouillé Vidéo premium

Cette vidéo est réservée aux détenteurs de l’offre premium.
Envie de nous rejoindre ?

Choisir une formule

C’est parce que votre bloc n’arrive plus à retrouver les attributs par rapport aux instructions du block.json, et qu’en base c’est toujours l’ancienne qui est enregistrée.

Une erreur s'affiche sur le bloc car Gutenberg n'arrive plus à l'interpréter correctement.
Une erreur de bloc Gutenberg

Dans la console on verra même une erreur plus détaillée avec ce qu’a reçu Gutenberg par rapport à ce qu’il attendait :

La console du navigateur affiche plus de détails sur l'erreur, et ce qu'il attendant face à ce qu'il a réellement reçu.
Le code attendu par Gutenberg face au code obtenu

C’est un message que l’on vois très souvent lorsqu’on on créé nos blocs.

Pendant la phase de développement ce n’est pas grave, il suffit de supprimer le bloc et de le recréer.

Mais lorsque vous aurez une extension opérationnelle et utilisée, vous ne pourrez 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 comment mettre en place les dépréciations de blocs 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.

Le répertoire Github de Gutenberg

Avant de terminer, et pour les plus curieux d’entre-vous, je vous propose d’aller jeter un œil au répertoire Github du projet Gutenberg.

verrouillé Vidéo premium

Cette vidéo est réservée aux détenteurs de l’offre premium.
Envie de nous rejoindre ?

Choisir une formule

On va y retrouver toutes les librairies qui gravitent autour Gutenberg, dont create-react-block, les composants de l’éditeur, les composants généraux React…

Le répertoire Github

Et pour cause, c’est ce que l’on appelle un monorepo : un seul répertoire Github pour héberger tous les projets. Cette approche est d’ailleurs très prisée dans le développement d’applications web modernes.

Le répertoire Github de Gutenberg en monorepo et de toutes les librairies qui gravitent autour du projet.
Le monorepo Github du projet Gutenberg

C’est dans le dossier package que sont listées les librairies que l’on utilise et qu’on va utiliser dans la suite de la formation. On remarque par exemple :

  • create-block : la librairie qui nous a permis de générer la base du plugin, avec le compilateur prêt à l’emploi ;
  • api-fetch : une fonction permettant de faciliter les appels API vers WordPress ;
  • block-library : c’est ici que vous retrouverez tous les blocs natifs de Gutenberg.
  • block-editor : stocke les composants de l’éditeur comme le RichText ;
  • components : c’est ici que sont entreposés les composants d’interface généraux comme les boutons on/off, le sélecteur de couleur…
  • core-data : une librairie qui permet de récupérer facilement des données de Gutenberg et du backend ;
  • interactivity : un script WordPress très pratique qui simplifie l’écriture de JS et remplace jQuery.

Comme vous pouvez le constater en scrollant dans le package, on remarque qu’il y a énormément de sous-projets qui font tourner Gutenberg. C’est ici qu’on prend conscience de l’énorme travail effectué durant toutes ces années par les core commiters.

D’ailleurs, on verra bon nombre de ces concepts dans la suite de la formation !

Conseil

Quand la documentation est un peu chiche sur un sujet, vous pouvez venir étudier le code des différentes librairies ou composants afin de trouver vos réponses.

Information

Si vous trouvez des bugs et que vous voulez contribuer à Gutenberg, vous pouvez ouvrir des tickets dans l’onglet « Issues » du projet.

La librairie des blocs natifs

À titre d’exemple, on va aller explorer le package des blocs natifs. Pour cela on se rend dans packages/block-library/src.

Ici, l’architecture est simple : un dossier = un bloc natif. On va aller voir du côté du bloc image par exemple.

À l’intérieur du dossier, rien de bien nouveau : on retrouve une structure de bloc classique avec notamment la présence des fichiers block.json, edit.js, save.js

Le projet Gutenberg dans Github. On remarque ici le dossier hébergeant le bloc natif Image et les fichiers JS qui le composent.
Les blocs natifs suivent la même structure que nos blocs sur mesure

En allant faire un tour du côté du block.json, on devrait trouver les attributs du bloc :

JSON
block.json

Je ne les mets pas tous ici, car il y en a plus de 15 actuellement !

Si vous allez faire un tour dans edit.js cette fois, on retrouve la même structure de blocs que celle qu’on a déjà vue précédemment, mais on constate par contre que le code est bien plus fourni que nos blocs.

JSX
edit.js

En effet, il y a énormément de choses à gérer dans la gestion des images avec WordPress.

Quant au fichier save.js, c’est beaucoup plus simple, et on peut observer comment est généré le code de l’image notamment à l’aide de la balise <figure>.

Si vous voulez un exemple plus simple, allez faire un tour du côté du code du bloc « paragraphe ». Mais là aussi, vous verrez que WordPress fait énormément de traitement sur ce bloc en apparence aussi minimaliste.


Maintenant que vous avez une bonne compréhension des rouages de Gutenberg, on va pouvoir reprendre le développement de nos blocs.

Mais avant ça, je vous propose qu’on se familiarise avec les syntaxes un peu particulières de React et du JavaScript moderne.

3

Questions, réponses et commentaires

  1. 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.

    1. 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).

  2. 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 !

Laisser un commentaire