Gutenberg est l’éditeur par défaut de WordPress. L’éditeur vous permet de créer et de styliser du contenu à l’aide de blocs discrets pour le texte, les images, les vidéos et d’autres éléments du site via une interface de type glisser-déposer. Cette approche améliore la flexibilité et les capacités de conception de WordPress.

Ce guide explique comment analyser le contenu de Gutenberg en HTML à l’aide de l’API REST de WordPress dans un site statique Next.js.

Pré-requis

Pour suivre ce guide, vous avez besoin de :

Récupérer le contenu de Gutenberg à l’aide d’une API REST

Pour interagir avec votre site WordPress de manière programmatique et récupérer le contenu structuré dans les blocs Gutenberg, vous utilisez l’API REST de WordPress ou l’extension WPGraphQL. Ces outils vous permettent de récupérer votre contenu WordPress au format JSON.

Pour activer l’accès aux données JSON via l’API REST, modifiez les réglages WordPress de vos permaliens en vous éloignant de « Sumple » Cela permet d’accéder à l’API par le biais d’une URL structurée, comme suit :

https://yoursite.com/wp-json/wp/v2

En effectuant des requêtes API à cette URL, vous pouvez récupérer de manière programmatique diverses informations et effectuer des opérations sur votre site WordPress. Par exemple, vous pouvez récupérer une liste d’articles en envoyant une requête GET à :

https://yoursite.com/wp-json/wp/v2/posts

Cela renverra un objet JSON contenant des informations sur les articles de votre site WordPress, y compris les titres, le contenu, les détails de l’auteur, et plus encore.

Analyser les blocs Gutenberg en HTML

Lorsque vous récupérez des articles d’un site WordPress qui utilise l’éditeur Gutenberg, le contenu stocké dans la base de données peut comporter un mélange de métadonnées HTML et JSON pour décrire différents types de blocs, tels que les citations et les galeries. Par exemple :

<!-- wp:quote {"className":"inspirational-quote","style":{"typography":{"fontSize":"large"}}} -->
<blockquote class="wp-block-quote inspirational-quote has-large-font-size"><p>“The journey of a thousand miles begins with one step.”</p><cite>Lao Tzu</cite></blockquote>
<!-- /wp:quote -->

<!-- wp:gallery {"ids":[34,35],"columns":2,"linkTo":"none","sizeSlug":"medium","className":"custom-gallery"} -->
<ul class="wp-block-gallery columns-2 is-cropped custom-gallery"><li class="blocks-gallery-item"><figure><img src="http://example.com/wp-content/uploads/2021/09/image1-300x200.jpg" alt="A breathtaking view of the mountains" class="wp-image-34"/></figure></li><li class="blocks-gallery-item"><figure><img src="http://example.com/wp-content/uploads/2021/09/image2-300x200.jpg" alt="Serene lakeside at dawn" class="wp-image-35"/></figure></li></ul>
<!-- /wp:gallery -->

Cet extrait illustre deux blocs Gutenberg : une citation et une galerie. Chacun est complété par des métadonnées JSON encapsulées dans des commentaires HTML. Les métadonnées définissent des attributs tels que les noms de classe, les styles et d’autres configurations pertinentes pour la présentation du bloc.

Lorsque vous récupérez ces blocs via l’API WordPress REST ou WPGraphQL, WordPress les traite, transformant la combinaison des métadonnées HTML et JSON en éléments HTML entièrement rendus que vous pouvez directement incorporer dans des pages web. Le HTML transformé pour les blocs ci-dessus apparaitrait comme suit :

<blockquote class="wp-block-quote inspirational-quote has-large-font-size"><p>“The journey of a thousand miles begins with one step.”</p><cite>Lao Tzu</cite></blockquote>

<ul class="wp-block-gallery columns-2 is-cropped custom-gallery">
  <li class="blocks-gallery-item"><figure><img loading="lazy" src="http://example.com/wp-content/uploads/2021/09/image1-300x200.jpg" alt="A breathtaking view of the mountains" class="wp-image-34" sizes="(max-width: 300px) 100vw, 300px" /></figure></li>
  <li class="blocks-gallery-item"><figure><img loading="lazy" src="http://example.com/wp-content/uploads/2021/09/image2-300x200.jpg" alt="Serene lakeside at dawn" class="wp-image-35" sizes="(max-width: 300px) 100vw, 300px" /></figure></li>
</ul>

Pour les développeurs qui construisent des applications découplées ou headless en utilisant des frameworks JavaScript comme Next.js, il s’agit d’une méthode simple pour afficher le contenu en injectant directement le HTML dans la page à l’aide de la propriété dangerouslySetInnerHTML pour rendre le balisage.

<div dangerouslySetInnerHTML={{ __html: <raw_html_string> }} />

En outre, vous pouvez avoir besoin d’effectuer un formatage supplémentaire pour des éléments tels que les liens et de gérer les caractères de nouvelle ligne en excès (\n), ce que ce guide explique plus loin.

Analyser le contenu des blocs Gutenberg dans un site statique Next.js

Dans cette section, nous allons récupérer le contenu de WordPress dans un projet Next.js, puis analyser les blocs Gutenberg en HTML.

  1. Commencez par configurer une fonction pour récupérer les articles de votre site WordPress. Ouvrez le fichier src/page.js dans votre projet et remplacez son contenu par l’extrait de code suivant :
    const getWpPosts = async () => {
    	const res = await fetch('https://yoursite.com/wp-json/wp/v2/posts');
      	const posts = await res.json();
    	return posts;
    };

    Cette fonction asynchrone effectue une requête à l’API REST de WordPress. Elle récupère tous les articles disponibles sur votre site et les renvoie sous forme de tableau.

  2. Ensuite, nous allons utiliser les articles récupérés dans un simple composant de page Next.js en enregistrant les articles dans la console et en affichant un message d’accueil basique :
    const page = async () => {
      const posts = await getWpPosts();
      console.log(posts);
      
      return (
        <div>
          <h1>Hello World</h1>
        </div>
      );
    };
    
    export default page;

    Lorsque vous exécutez votre projet à l’aide de npm run dev, il affiche le message « Hello World » et enregistre les articles récupérés dans le terminal.

    [
      {
        "_links" : {
          "about" : [...],
          "author" : [...],
          "collection" : [...],
          "curies" : [...],
          "predecessor-version" : [...],
          "replies" : [...],
          "self" : [...],
          "version-history" : [...],
          "wp:attachment" : [...],
          "wp:term" : [...]
        },
        "author" : 1,
        "categories" : [...],
        "comment_status" : "open",
        "content" : {
          "protected" : false,
          "rendered" : "\n<p>Fire, a primal force, captivates with its <strong>flickering flames</strong>, evoking both awe and caution. Its <quote>dance</quote> symbolizes destruction and renewal, consuming the old to make way for the new. While it warms our homes and hearts, fire demands respect for its power to devastate.</p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"250\" height=\"148\" src=\"https://img.example.com/wp-content/uploads/2024/02/burningbuilding.jpg\" alt=\"\" class=\"wp-image-14\"/></figure>\n\n\n\n<p>In ancient times, fire was a beacon of light and warmth, essential for survival. Today, it remains a symbol of human ingenuity and danger. From the comforting glow of a hearth to the destructive fury of wildfires, fire’s dual nature reminds us of our fragile relationship with the elements.</p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https://img.example.com/premium-photo/painting-burning-building-illuminated-by-bright-flames-night_168058-249.jpg?w=1380\" alt=\"\"/></figure>\n\n\n\n<p>You can check out other articles on our blog:</p>\n\n\n\n<ul>\n<li><a href=\"https://yoursite.com/?p=6\">Lorem Ipsum: Beginnings</a></li>\n\n\n\n<li><a href=\"https://yoursite.com/?p=9\">Lorem Ipsum: Act 2</a></li>\n\n\n\n<li><a href=\"https://yoursite.com/?p=11\">Lorem Ipsum: Act 3</a></li>\n</ul>\n"
        },
        "date" : "2024-02-27T12:08:30",
        "date_gmt" : "2024-02-27T12:08:30",
        "excerpt" : {
          "protected" : false,
          "rendered" : "<p>Fire, a primal force, captivates with its flickering flames, evoking both awe and caution. Its dance symbolizes destruction and renewal, consuming the old to make way for the new. While it warms our homes and hearts, fire demands respect for its power to devastate. In ancient times, fire was a beacon of light and warmth, […]</p>\n"
        },
        "featured_media" : 0,
        "format" : "standard",
        "guid" : {
          "rendered" : "https://yoursite.com/?p=13"
        },
        "id" : 13,
        "link" : "https://yoursite.com/?p=13",
        "meta" : {
          "footnotes" : ""
        },
        "modified" : "2024-02-29T16:45:36",
        "modified_gmt" : "2024-02-29T16:45:36",
        "ping_status" : "open",
        "slug" : "fire-fire",
        "status" : "publish",
        "sticky" : false,
        "tags" : [],
        "template" : "",
        "title" : {
          "rendered" : "Fire"
        },
        "type" : "post"
       },
      },
      ...
    ]

    Les objets JSON représentant les données individuelles des articles de Gutenberg comprennent divers champs, parmi lesquels les champs contenu et extrait sont renvoyés sous forme de blocs Gutenberg analysés en tant que chaines HTML.

  3. Pour rendre ce contenu HTML correctement dans Next.js, nous utilisons la propriété dangerouslySetInnerHTML:
    const page = async () => {
      const posts = await getWpPosts();
    
      return (
        <>
          <h1> Headless Blog </h1>
    
          <div>
            {posts.map((post) => (
              <Link href={'/blog/' + post.id} key={post.id}>
                <h2>
                  {post.title.rendered} <span>-></span>
                </h2>
                <div dangerouslySetInnerHTML={{ __html: post.excerpt.rendered }} />
              </Link>
            ))}
          </div>
        </>
      );
    };
    
    export default page;

    Dans ce composant mis à jour, nous mappons le tableau des articles récupérés pour générer une liste d’extraits d’articles. Chaque extrait est enveloppé dans un composant Link pour la navigation, affichant le titre de l’article et un extrait de son contenu.
    La propriété dangerouslySetInnerHTML est utilisée pour analyser et rendre le contenu HTML contenu dans le champ excerpt.rendered.

  4. Ensuite, créez un fichier blog/[id]/page.js dans le répertoire de l’application. Vous utilisez des dossiers pour définir des itinéraires. Ainsi, en créant un dossier blog, vous définissez la route blog. Vous combinez cela avec le routage dynamique pour générer des itinéraires pour chaque article.
  5. Chaque article possède un identifiant. Vous utilisez cet identifiant pour générer une route unique, /blog/{post_id}dans votre application. Ajoutez le code suivant :
    import Link from 'next/link';
    
    export async function generateStaticParams() {
        const res = await fetch('https://yoursite.com/wp-json/wp/v2/posts');
        const posts = await res.json();
        return posts.map((post) => {
            return {
                params: {
                    id: post.id.toString(),
                },
            };
        });
    }
    
    export async function getPost(id) {
        const response = await fetch('https://yoursite.com/wp-json/wp/v2/posts/' + id);
        const post = await response.json();
        return post;
    }

    La fonction generateStaticParams() génère statiquement des routes au moment de la construction en fonction de l’ID correspondant renvoyé pour chaque article. La fonction getPost() récupère les données Gutenberg de l’API REST pour l’article dont l’identifiant a été transmis.
    Une section précédente a montré un exemple de données Gutenberg analysées renvoyées par l’API REST pour un article. Pour l’instant, nous ne nous intéressons qu’au champ content.rendered:

    [
      {
        ...
        "content": {
          "rendered" : "\n<p>Fire, a primal force, captivates with its <strong>flickering flames</strong>, evoking both awe and caution. Its <quote>dance</quote> symbolizes destruction and renewal, consuming the old to make way for the new. While it warms our homes and hearts, fire demands respect for its power to devastate.</p>\n\n\n\n<figure> class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"250\" height=\"148\" src=\"https://img.example.com/wp-content/uploads/2024/02/burningbuilding.jpg\" alt=\"\" class=\"wp-image-14\"/></figure>\n\n\n\n<p>In ancient times, fire was a beacon of light and warmth, essential for survival. Today, it remains a symbol of human ingenuity and danger. From the comforting glow of a hearth to the destructive fury of wildfires, fire’s dual nature reminds us of our fragile relationship with the elements.</p>\n\n\n\n<figure> class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https://img.example.com/premium-photo/painting-burning-building-illuminated-by-bright-flames-night_168058-249.jpg?w=1380\" alt=\"\"/></figure>\n\n\n\n<p>You can check out other articles on our blog:</p>\n\n\n\n<ul>\n<li><a> href=\"https://yoursite.com/?p=6\">Lorem Ipsum: Beginnings</a></li>\n\n\n\n<li><a> href=\"https://yoursite.com/?p=9\">Lorem Ipsum: Act 2</a></li>\n\n\n\n<li><a> href=\"https://yoursite.com/?p=11\">Lorem Ipsum: Act 3</a></li>\n</ul>\n"
        },
        ...
      }
    ]

    Ce champ contient le code HTML brut de l’article. Il peut être rendu directement en utilisant la propriété dangerouslySetInnerHTML comme ceci : <div dangerouslySetInnerHTML={{ __html: <raw_html_string> }} />.

  6. Ensuite, vous pouvez traiter les données en analysant les liens internes et en redimensionnant les images. Installez le paquet html-react-parser pour simplifier le processus d’analyse des balises :
    npm install html-react-parser --save
  7. Ajoutez le code suivant au fichier blog/[id]/page.js:
    import parse, { domToReact } from "html-react-parser";
    
    /*
     * We use a regular expression (pattern) to match the specific URL you want to replace.
     * The (\d+) part captures the numeric ID after ?p=.
     * Then, we use the replacement string 'data-internal-link="true" href="/blog/$1"',
     * where $1 is a placeholder for the captured ID.
     */
    export function fixInternalLinks(html_string) {
      const pattern = /href="https:\/\/yoursite.com\/\?p=(\d+)"/g;
      const replacement = 'data-internal-link="true" href="/blog/$1"';
    
      return html_string.replace(pattern, replacement);
    }
    
    export function parseHtml(html) {
      // Replace 2+ sequences of '\n' with a single '<br />' tag
      const _content = html.replace(/\n{2,}/g, '<br />');
      const content = fixInternalLinks(_content);
    
      const options = {
        replace: ({ name, attribs, children }) => {
          // Convert internal links to Next.js Link components.
          const isInternalLink =
            name === "a" && attribs["data-internal-link"] === "true";
    
          if (isInternalLink) {
            return (
              <Link href={attribs.href} {...attribs}>
                {domToReact(children, options)}
              </Link>
        	  );
          } else if (name === "img") {
            attribs["width"] = "250";
            attribs["height"] = "150";
            return (
              <img {...attribs}/>
            );
          }
        },
      };
    
      return parse(content, options);
    }

    La fonction fixInternalLinks() utilise une expression régulière pour trouver des liens vers des articles de votre site WordPress à partir de la chaîne HTML. Dans le code HTML brut, vous pouvez voir que l’article contient une balise List avec des liens vers d’autres articles de votre site, remplaçant ces liens par des liens internes vers des itinéraires de votre site statique.
    La fonction parseHTML() détecte les séquences multiples de nouvelles lignes en excès, net les remplace par des balises <br />. Elle trouve également les liens internes et convertit les balises d’ancrage en balises Link. Enfin, cette fonction redimensionne les images à l’aide des attributs des balises.

  8. Pour générer l’interface utilisateur principale de chaque route dynamique, ajoutez le code suivant :
    export default async function Post({ params }) {
      const post = await getPost(params.id);
    
      const content = parseHtml(post.content.rendered);
    
      return (
        <>
          <h1>
            {post.title.rendered}
          </h1>
     	 
          <div>{content}</div>
        </>
      );
    }

    Après avoir analysé le HTML brut à partir des données Gutenberg, le code renvoie le JSX représentant l’interface utilisateur formatée de la page.

Enfin, lorsque vous exécutez votre projet, la page d’accueil affichera une liste d’articles sur votre WordPress. De plus, lorsque vous cliquez sur des articles individuels, vous verrez le contenu analysé de Gutenberg rendu correctement.

Déployer votre site statique Next.js sur Kinsta

Lorsque vous combinez WordPress headless avec des frameworks de pointe comme Next.js, trouver une solution de déploiement rentable devient essentiel, en particulier lorsque vous utilisez un hébergement WordPress puissant comme celui de Kinsta pour votre site WordPress. Le service d’hébergement de sites statiques de Kinsta offre un moyen transparent et abordable de mettre votre site en ligne.

Kinsta vous permet d’héberger gratuitement jusqu’à 100 sites web statiques. Tout d’abord, envoyez votre code à votre fournisseur Git préféré (Bitbucket, GitHub ou GitLab). Une fois que votre répertoire est prêt, suivez les étapes suivantes pour déployer votre site statique sur Kinsta :

  1. Connectez-vous ou créez un compte pour afficher votre tableau de bord MyKinsta.
  2. Autorisez Kinsta avec votre fournisseur Git.
  3. Cliquez sur Sites statiques dans la colonne latérale de gauche, puis cliquez sur Ajouter un site.
  4. Sélectionnez le dépôt et la branche à partir desquels vous souhaitez déployer.
  5. Attribuez un nom unique à votre site.
  6. Ajoutez les réglages de construction dans le format suivant :
    • Commande de construction: npm run build
    • Version du nœud: 18.16.0
    • Répertoire de publication: out
  7. Enfin, cliquez sur Créer un site.

Et le tour est joué ! En quelques secondes, vous disposez d’un site déployé. Un lien est fourni pour accéder à la version déployée de votre site. Vous pourrez par la suite ajouter votre domaine personnalisé et votre certificat SSL si vous le souhaitez.

Comme alternative à l’hébergement de sites statiques, vous pouvez opter pour le déploiement de votre site statique avec le service d’hébergement d’applications de Kinsta, qui offre une plus grande flexibilité d’hébergement, un plus large éventail d’avantages et l’accès à des fonctionnalités plus robustes – comme l’évolutivité, le déploiement personnalisé à l’aide d’un fichier Docker, et des analyses complètes englobant des données en temps réel et historiques. Vous n’avez pas non plus besoin de configurer votre projet Next.js pour un rendu statique.

Résumé

Ce guide a expliqué comment intégrer et analyser le contenu des blocs Gutenberg efficacement en tant que HTML via l’API WordPress. Cela rend le rendu de tout type de contenu sur votre frontend possible lorsque vous utilisez WordPress headless.

Vous pouvez héberger votre WordPress headless sur notre service d’hébergement WordPress infogéré et déployer votre site statique sur notre service d’hébergement de site statique. Cela signifie que tout ce qui concerne votre site se trouve dans un seul tableau de bord : MyKinsta.

En choisissant Kinsta, vous bénéficiez d’un fournisseur d’hébergement qui donne la priorité à la performance et à l’évolutivité optimales du site, tout en renforçant les sites web avec des mesures de sécurité avancées. Essayez Kinsta dès aujourd’hui !

Que pensez-vous de WordPress headless et de son rendu ? Vous avez une meilleure façon d’intégrer les blocs Gutenberg ? Partagez vos idées dans la section des commentaires !

Jeremy Holcombe Kinsta

Rédacteur en chef du contenu et du marketing chez Kinsta, développeur web WordPress et rédacteur de contenu. En dehors de WordPress, j'aime la plage, le golf et le cinéma. J'ai aussi des problèmes avec les personnes de grande taille ;).