Formation « Créer des blocs avec Gutenberg »

Gérer la dépréciation de vos blocs

Lecture : 4 minutes • 0

Que se passe-t'il lorsque l'on change le HTML de la méthode save ? Gutenberg renvoie une erreur sur le bloc qui semble non récupérable. Afin d'éviter cela, on peut définir une migration pour convertir les blocs dépréciés.

Le problème du changement de HTML

Si vous modifiez le rendu HTML d’un bloc dans sa méthode save, la prochaine fois que vous chargerez un article comprenant ce bloc, vous ferez face à cette erreur :

un bloc qui a été modifié
Une erreur de bloc Gutenberg

Cliquez sur Solutionner afin de comparer le code reçu et le code attendu :

Solutionner un bloc cassé
Solutionner un bloc cassé

Vous aurez également l’erreur dans la console mais c’est beaucoup moins lisible :

Le code attendu par Gutenberg face au code obtenu

Autant ce n’est pas gênant lorsque vous développez vos premiers blocs, autant cela va poser un gros souci lorsque vous voudrez mettre à jour le rendu d’un bloc déjà utilisé maintes fois par les rédacteurs du site.

Pour cela il existe une méthode de dépréciation qui va nous permettre de garder une trace des anciens attributs, afin que l’éditeur ne nous mette pas une erreur.

D’après le handbook Gutenberg, les développeurs ont pensé à tout, heureusement pour nous !

On va utiliser la méthode deprecated, que l’on place généralement après edit et save, pour nous sortir de ce mauvais pas.

Dépréciation lors d'un changement de HTML

Prenons le cas le plus simple : ici seul le HTML change : le bloc rendait auparavant un <p>, et maintenant une <div>.

Voici le code :

JS
const attributes = {
    text: {
        type: 'string',
      	source: 'text',
      	selector: 'content',
    }
};

registerBlockType( 'capitainewp/depreciation', {

    // title, description, keywords ...

    attributes: attributes,

    save( props ) {
        return <div className="content">{ props.attributes.text }</div>;
    },

    deprecated: [ // Ancienne version 
        {
            attributes: attributes, // Mêmes attributs

            save( props ) { // Ce qui était enregistré avant
                return <p className="content">{ props.attributes.text }</p>;
            },
        }
    ]
} );

Le but ici est de définir les éventuels changement d’attributs et HTML dans la méthode save. Tout ce qui se trouve dans la méthode deprecated concerne l’ancienne version de notre bloc.

Les attributs restent les mêmes, du coup au lieu de les redéfinir, je vais les déclarer en amont dans une constante (après tout j’ai le droit) et je les appelle dans le bloc, et dans la dépréciation. De cette manière j’évite une répétition et je reste DRY (Don’t Repeat Yourself).

Le seul changement est dans deprecated / save : j’indique l’ancienne version, qui comprenait le paragraphe à la place du bloc. Notez que la class content n’a pas changé.

Dépréciation des attributs

Maintenant, pour épicer un peu le tout, on va changer le nom d’un attribut. Imaginons que l’on veuille renommer text par content.

Voyons comment gérer ce cas au niveau du code :

JS
registerBlockType( 'gutenberg/block-with-deprecated-version', {

    //  title, description, keywords ...

    attributes: {
        content: { // le nouveau nom
            type: 'string',
      		source: 'text',
      		selector: 'content',
        }
    },

    save( props ) {
        return <div className="content">{ props.attributes.text }</div>;
    },

    deprecated: [
        {
            attributes: {
                text: { // L'ancien nom
                    type: 'string',
      				source: 'text',
      				selector: 'content',
                }
            },

            migrate( { text } ) { // La fonction permettant de migrer text -> content
                return {
                    content: text
                };
            },

            save( props ) { // L'ancien HTML
                return <p className="content">{ props.attributes.text }</p>;
            },
        }
    ]
} );

Bon déjà cette fois, comme les attributs sont différents, on ne les met plus en commun.

Dans la nouvelle version du bloc, l’attribut s’appelle content. Dans le deprecated, il s’appelait text.

On voit aussi dans deprecated une méthode migrate qui permet de faire la conversion. Ici on dit que si le bloc a reçu l’ancien HTML, il prend la valeur de text et l’enregistre dans la nouvelle version content.

Et le tour est joué !

Au final c’est plutôt facile de gérer la dépréciation des blocs, et c’est tant mieux. Cela permet de penser sereinement au futur sans casser le passé.

Gérer plusieurs dépréciations

Un bloc vit avec le temps, et risque d’évoluer à plusieurs reprises. Si vous avez remarqué, notre deprecated est une liste (un tableau non associatif en JS), du coup il indique que l’on peut mettre plusieurs objets dépréciation à l’intérieur.

JS
registerBlockType( 'gutenberg/block-with-deprecated-version', {

    //  title, description, keywords ...

    attributes: {
        content: { // le nouveau nom
            type: 'string',
      		source: 'text',
      		selector: 'content',
        }
    },

    save( props ) {
        return <div className="content">{ props.attributes.text }</div>;
    },

    deprecated: [
      	// version N - 1
        {  
            attributes: { ... },
            migrate( {} ) { return ... },
            save( props ) { return ... },
        },
        
        // version N - 2
        { 
            attributes: { ... },
            migrate( {} ) { return ... },
            save( props ) { return ... },
        }
        // ...
    ]
} );

Et si vous n’en n’avez pas eu assez, la doc officielle montre un autre cas encore plus poussé d’une transformation d’un attribut en sous-bloc.

En tous cas ce concept est hyper important, puisque sans lui vous ne pouvez pas modifier le rendu d’un bloc ou un attribut sans casser la compatibilité des blocs déjà écrits par vos utilisateurs.

Ne leur donnons donc pas une raison de pousser une gueulante !

0

Questions, réponses et commentaires

    Laisser un commentaire