vendredi 25 septembre 2026

À propos

Contact

Blocs Gutenberg

Créer un bloc Gutenberg personnalisé avec registerBlockType, sans block.json

Gutenberg tourne désormais sur la majorité des sites WordPress. Voici comment coder un bloc « encadré d'alerte » de A à Z, avec webpack et registerBlockType.

Par Clément Hadrot • 18 février 2020 • 7 min de lecture • Aucun commentaire
Créer un bloc Gutenberg personnalisé avec registerBlockType, sans block.json

Depuis la sortie de WordPress 5.0 fin 2018, l’éditeur Gutenberg s’est installé durablement dans le cœur du CMS. En ce début 2020, de plus en plus de clients demandent des mises en page qu’aucun plugin de champs personnalisés ne couvre correctement : un encadré d’alerte avec une couleur au choix, une citation stylée, un bloc « chiffre clé ». La réponse la plus robuste, c’est d’écrire son propre bloc.

Beaucoup de tutoriels s’appuient déjà sur @wordpress/create-block, mais ce générateur est encore jeune et masque des rouages qu’il vaut mieux comprendre avant de s’en remettre à lui. Dans cet article, on construit un bloc « encadré d’alerte » à la main : configuration webpack, appel à registerBlockType, fonctions edit() et save(), puis enregistrement côté PHP. Pas de générateur, pas de magie : juste les briques de l’API telles qu’elles existent aujourd’hui.

Pourquoi coder un bloc plutôt qu’utiliser un shortcode

Avant Gutenberg, on aurait résolu ce besoin avec un shortcode et un peu de CSS. Le problème, c’est que l’auteur de contenu ne voit rien tant qu’il n’a pas prévisualisé la page : aucun retour visuel immédiat, aucun contrôle simple des options. Un bloc personnalisé, lui, s’affiche directement dans l’éditeur grâce à sa fonction edit(), avec les mêmes composants que ceux utilisés par les blocs natifs (paragraphe, image, colonnes…).

Autre avantage : le contenu du bloc est stocké de façon structurée dans le contenu de l’article, sous forme de commentaires HTML délimiteurs lisibles par Gutenberg. On garde donc la portabilité du contenu WordPress classique, tout en offrant une interface d’édition moderne.

Mettre en place l’environnement de build

Gutenberg s’appuie sur React via les paquets @wordpress/element (une fine surcouche de React) et sur JSX ou createElement. Comme aucun navigateur ne comprend nativement JSX ni les modules ES, il faut un outil de build. Nous partons ici sur une configuration webpack manuelle, plus proche de ce que fait réellement @wordpress/scripts en coulisses.

Dans le dossier de votre plugin, installez les dépendances suivantes :

npm init -y
npm install --save-dev webpack webpack-cli @babel/core @babel/preset-env @babel/preset-react babel-loader
npm install --save @wordpress/element @wordpress/blocks @wordpress/block-editor @wordpress/components
L'essentiel à retenir : Configurer webpack et @wordpress/element pour builder un bloc ; Comprendre edit() et save() sans framework caché ; Enregistrer le bloc en JS et en PHP proprement

Notez le paquet @wordpress/block-editor : c’est le nom retenu depuis fin 2019 pour ce qui s’appelait auparavant @wordpress/editor côté composants d’édition de blocs. Les deux coexistent encore dans la documentation, mais pour un bloc neuf, privilégiez @wordpress/block-editor.

Le fichier webpack.config.js

const path = require( 'path' );

module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve( __dirname, 'build' ),
        filename: 'index.js',
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: 'babel-loader',
            },
        ],
    },
    externals: {
        react: 'React',
        '@wordpress/element': 'wp.element',
        '@wordpress/blocks': 'wp.blocks',
        '@wordpress/block-editor': 'wp.blockEditor',
        '@wordpress/components': 'wp.components',
    },
};

Le bloc externals est capital : il indique à webpack de ne pas embarquer ces bibliothèques dans le bundle, puisque WordPress les expose déjà globalement via les variables wp.element, wp.blocks, etc. C’est ce qui évite de dupliquer React dans chaque plugin actif.

Écrire le bloc en JavaScript

Créez src/index.js. On y importe registerBlockType depuis @wordpress/blocks, ainsi que RichText et InspectorControls depuis @wordpress/block-editor pour permettre l’édition de texte enrichi et un panneau de réglages.

import { registerBlockType } from '@wordpress/blocks';
import { RichText, InspectorControls } from '@wordpress/block-editor';
import { PanelBody, SelectControl } from '@wordpress/components';
import { __ } from '@wordpress/i18n';

registerBlockType( 'wpmoderne/encadre-alerte', {
    title: __( 'Encadré d\'alerte', 'wpmoderne' ),
    icon: 'warning',
    category: 'common',
    attributes: {
        message: {
            type: 'string',
            source: 'html',
            selector: 'p',
        },
        type: {
            type: 'string',
            default: 'info',
        },
    },

    edit( { attributes, setAttributes } ) {
        const { message, type } = attributes;

        return [
            <InspectorControls key="inspector">
                <PanelBody title={ __( 'Réglages', 'wpmoderne' ) }>
                    <SelectControl
                        label={ __( 'Type d\'alerte', 'wpmoderne' ) }
                        value={ type }
                        options={ [
                            { label: 'Information', value: 'info' },
                            { label: 'Avertissement', value: 'warning' },
                            { label: 'Erreur', value: 'error' },
                        ] }
                        onChange={ ( newType ) => setAttributes( { type: newType } ) }
                    />
                </PanelBody>
            </InspectorControls>,
            <div key="edit" className={ `wpmoderne-alerte wpmoderne-alerte--${ type }` }>
                <RichText
                    tagName="p"
                    value={ message }
                    onChange={ ( newMessage ) => setAttributes( { message: newMessage } ) }
                    placeholder={ __( 'Votre message d\'alerte…', 'wpmoderne' ) }
                />
            </div>,
        ];
    },

    save( { attributes } ) {
        const { message, type } = attributes;
        return (
            <div className={ `wpmoderne-alerte wpmoderne-alerte--${ type }` }>
                <RichText.Content tagName="p" value={ message } />
            </div>
        );
    },
} );

Deux points méritent votre attention. D’abord, edit() retourne un tableau d’éléments : en JSX classique, il faudrait un fragment, mais à cette date, les fragments <></> sont encore mal supportés par la configuration Babel par défaut de Gutenberg, donc le tableau avec des clés (key) reste la pratique la plus sûre. Ensuite, save() doit produire un HTML strictement identique à celui que Gutenberg va comparer lors de la validation du contenu : toute divergence provoquera une erreur de validation du bloc à la réouverture de l’article.

Enregistrer le bloc côté PHP

Le JavaScript seul ne suffit pas : WordPress doit charger le script et, idéalement, enregistrer le bloc côté serveur pour que l’éditeur connaisse son existence même avant l’exécution du JS. On utilise register_block_type() dans le fichier principal du plugin.

<?php
/**
 * Plugin Name: WP Moderne - Encadré d'alerte
 */

function wpmoderne_register_alerte_block() {
    wp_register_script(
        'wpmoderne-alerte-block',
        plugins_url( 'build/index.js', __FILE__ ),
        array( 'wp-blocks', 'wp-element', 'wp-block-editor', 'wp-components', 'wp-i18n' ),
        filemtime( plugin_dir_path( __FILE__ ) . 'build/index.js' )
    );

    wp_register_style(
        'wpmoderne-alerte-style',
        plugins_url( 'style.css', __FILE__ ),
        array(),
        '1.0.0'
    );

    register_block_type( 'wpmoderne/encadre-alerte', array(
        'editor_script' => 'wpmoderne-alerte-block',
        'style'         => 'wpmoderne-alerte-style',
    ) );
}
add_action( 'init', 'wpmoderne_register_alerte_block' );

À cette date, register_block_type() attend soit un chemin vers un fichier block.json (fonctionnalité qui n’existe pas encore), soit — comme ici — un nom de bloc suivi d’un tableau d’arguments : editor_script, editor_style, script, style, render_callback, etc. C’est cette seconde forme que vous utiliserez systématiquement pour l’instant.

Les erreurs les plus fréquentes en démarrant

  • Oublier une dépendance dans le tableau de wp_register_script(), ce qui provoque un wp is not defined dans la console.
  • Modifier save() après avoir déjà publié des articles avec l’ancienne version du bloc, ce qui casse la validation à la réouverture.
  • Confondre category: 'common' avec une catégorie personnalisée non déclarée : le bloc disparaît alors silencieusement de l’inserteur.
  • Charger le script sur le front-end sans le vouloir, en utilisant script au lieu d’editor_script.

Sur un projet client, prenez l’habitude de versionner le fichier build/index.js compilé ou d’automatiser le build en intégration continue : c’est le piège numéro un des livraisons de blocs personnalisés.

En résumé

Un bloc Gutenberg minimal tient en trois pièces : un point d’entrée JavaScript qui appelle registerBlockType, une configuration webpack qui transforme ce JSX en JavaScript compréhensible par le navigateur, et un enregistrement PHP qui relie le tout via register_block_type(). Ce n’est pas la voie la plus rapide — un générateur automatiserait une bonne partie de cette tuyauterie — mais c’est la voie qui vous permet de comprendre exactement ce que fait votre code, et de déboguer sereinement le jour où quelque chose casse en production.

Dans un prochain article, nous détaillerons en profondeur le système d’attributs de blocs : les différentes sources possibles, leurs pièges, et comment choisir la bonne stratégie de stockage selon vos besoins.

Partager :

À propos de l'auteur

Clément Hadrot

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi