Publié le

Rendre un bloc Gutenberg dynamique avec Twig et Timber

Twig
WordPress

Récemment, j'ai entrepris d'approfondir le "nouvel" éditeur Gutenberg de WordPress pour enfin l'adopter et proposer une meilleure expérience d'édition à mes clients. Ce déclic est arrivé lorsque j'ai vu les vidéos de l'étude de cas de 10up à propos de la réalisation du site de la Maison Blanche.

Enfin, j'ai compris que Gutenberg ne se limitait pas simplement à un assemblage de composants atomiques laborieux à faire évoluer et à maintenir, mais qu'il était possible de l'utiliser pour produire des composants plus larges comme des sections de site, des cartes, des layouts de page, etc.

D'abord confus par le modèle de données utilisé pour enregistrer les blocs en base de données et sa fragilité lors de la modification de blocs existants, j'ai alors découvert qu'en utilisant la variante dynamique des blocs, il est possible d'effectuer des modifications du rendu sur tout le site à la fois en modifiant ses templates associées sans avoir à modifier chaque page individuellement.

Les avantages de Gutenberg

L'avantage de cette solution est clair comparé à l'utilisation d'ACF et de son champ flexible : le client peut simplement cliquer sur les éléments qu'il veut modifier sur la page et voir le résultat en direct – un vrai WYSIWYG dans son sens le plus pur.

ACF permet tout de même la création de blocs rendus côtés serveur dans l'admin. Je trouve cependant celle solution non idéale de part la différence dans l'utilisation pour le client final entre l'édition des contenus directement où ils sont affichés sur la page contre l'utilisation de champs dans la barre latérale de l'éditeur et les délais de chargement associés dûs à l'utilisation de l'API WordPress pour la communication client-serveur dans le rendu de ces blocs.

Seulement voilà, même si Gutenberg utilisé de cette façon c'est super à l'utilisation, le développement de ses blocs m'a quelque peu rebuté lors de mes premiers expérimentations avec.

En effet, pour produire un résultat aussi qualitatif que celui du site du site de la Maison Blanche évoqué plus haut, il faut d'une part développer le composant une première fois avec React pour l'édition dans l'éditeur, puis une seconde fois en PHP pour le rendu front.

PHP ? Et mes templates Twig alors ? Et la réutilisation de templates ?

Développement de thèmes WordPress avec Timber et Twig

Timber est un module permettant l'utilisation de Twig avec WordPress. Il permet une séparation claire entre la logique (récupération des posts avec WP_Query, fonctionnalités customs, etc.) et l'affichage en front se rapprochant ainsi d'une architecture type MVC.

Depuis que j'ai commencé à l'utiliser il y a 5 ans, j'ai développé tous mes thèmes WordPress avec et ai même converti certains de mes clients en agence à son utilisation tant l'expérience de développement est supérieure comparée à l'utilisation des templates php de base souvent parsemées de morceaux de logique çà et là difficiles à maintenir dans le temps.

D'abord utilisé comme moteur de rendu des projets Symfony puis utilisé par Drupal pour ne citer que lui, Twig permet une grande flexibilité dans le développement front en facilitant la réutilisation de layouts, la création de composants chers aux développeurs front et plus généralement des pratiques devenues standards dans le développement toutes technologies confondues.

Utilisation de Timber et Twig avec Gutenberg

Voulant conserver mes bonnes pratiques de développement et un écosystème que je connais bien, j'ai donc cherché un moyen pour développer des blocs Gutenberg personnalisés et dynamiques avec un moteur de rendu Twig.

En creusant dans le cœur du code de WordPress et de Gutenberg, j'ai trouvé cette solution qui s'intègre parfaitement à mon utilisation de Timber :

add_filter('block_type_metadata_settings', function ($settings, $metadata) {
   if (! empty($metadata['render'])) {
      $template_path = wp_normalize_path(
         realpath(
            dirname($metadata['file']) . '/' .
            remove_block_asset_path_prefix($metadata['render'])
         )
      );

      if (str_ends_with($template_path, '.twig')) {
         $settings['render_callback'] = function ($attributes, $content, $block) use ($template_path) {
            $content = Timber::compile($template_path, [
               'attributes' => $attributes,
               'content' => $content,
               'block' => $block,
            ]);

            return $content;
         };
      };
   };

   return $settings;
}, 10, 2);

Ce morceau de code se base sur les métadonnées des blocs définies dans leur fichier block.json, la méthode recommandée par WordPress pour déclarer ses blocs.

Une des entrées de ce fichier permet de définir la template à utiliser pour son rendu, dans la plupart des cas "render": "file:./render.php".

Pour mes blocs, il me suffit donc de changer cette ligne par "render": "file:./render.twig". Le morceau de code ci-dessus reconnaissant ainsi l'utilisation d'une template Twig, il modifie le render_callback du bloc pour compiler sa template de rendu avec Twig grâce à la méthode Timber::compile.

À l'utilisation, je peux donc désormais faire mon rendu en Twig en utilisant les mêmes méthodes que ceux définis en PHP en utilisant les attributs, les InnerBlocks, les fonctions wrapper, etc.

<section {{
  function(
    'get_block_wrapper_attributes',
    {
      class: 'alignfull p-8'
    }
  )
  }}>
  <p class="text-2xl font-semibold">
    {{ attributes.content }}
  </p>
</section>

Mon projet starter pour le développement de thèmes Gutenberg avec Twig et TailwindCSS

Vous l'aurez remarqué, j'utilise des classes TailwindCSS dans mes templates Twig. Autre technologie que je n'ai plus quittée depuis sa découverte, je l'ai intégrée à mon thème de base pour me permettre de développer encore plus rapidement sans avoir à me soucier des différents fichiers de styles côté front et côté éditeur avec Gutenberg.

Parce que mon besoin est assez custom et sort de ce qu'il est possible de faire nativement avec WordPress, j'ai dû écrire une configuration webpack personnalisée plutôt que d'utiliser @wordpress/scripts pour compiler mes blocs, leurs templates et leurs assets.

Tout cela étant fastidieux à mettre en place, j'ai décidé de créer un starter theme public utilisable comme template disponible en Open Source.

Vous pouvez le retrouver à cette adresse sur GitHub.

En plus du rendu Twig des blocs, il inclue d'autres fonctionnalités pour moderniser encore un peu plus le développement de thèmes WordPress :

  • Utilisation de TailwindCSS pour les styles
  • Utilisation de Timber et Twig pour le rendu des templates
  • Utilisation de l'injection de dépendance et de classes pour l'organisation des fonctionnalités du thème
  • Ajout de services permettant la création facilitée de nouveaux Custom Post Types et Menus
  • Utilisation du composant de gestion d'erreur de Symfony
  • Création de blocs customisés utilisant Twig avec le cli @wordpress/create-block et une template locale

J'ai eu l'occasion d'utiliser cette stack de manière professionnelle et elle me permet une vélocité de développement comparable au développement de thèmes avec l'éditeur classique avec l'avantage d'offrir à mes clients une expérience d'édition incomparable.


J'espère que cette template vous convaincra enfin de passer (ou tout du moins de donner une nouvelle chance) à Gutenberg en conservant les bonnes pratiques que nous avons construit au fur et à mesure des années du développement et de l'évolution de WordPress.