Tout bloc suffisamment utilisé finit un jour par changer : un attribut renommé, une structure HTML simplifiée, une balise <div> remplacée par une balise sémantique plus pertinente. Le problème, c’est que le contenu déjà publié contient le markup généré par l’ancienne version du bloc, figé en base de données au format HTML avec ses commentaires <!-- wp:... -->. Sans précaution, la nouvelle version du bloc refuse ce markup et affiche une erreur de validation dans l’éditeur.
C’est exactement le rôle de la propriété deprecated de registerBlockType : elle permet de déclarer une ou plusieurs anciennes définitions du bloc, avec une logique de migration vers la version actuelle, sans jamais toucher au contenu déjà stocké.
Comment Gutenberg valide un bloc sauvegardé
À l’ouverture de l’éditeur, chaque bloc parsé dans le contenu est comparé au résultat de sa fonction save() actuelle. Si le HTML généré correspond, tout va bien. S’il diffère, ne serait-ce que par un espace ou un attribut manquant, Gutenberg considère le bloc comme invalide et propose de le récupérer tel quel en HTML brut, ou de tenter une réparation automatique.
C’est précisément ce scénario que deprecated permet d’éviter : plutôt que de laisser Gutenberg constater une incohérence, on lui fournit explicitement les anciennes versions possibles du bloc et la marche à suivre pour chacune.
Anatomie d’une déprécation

Prenons un bloc « bandeau d’alerte » dont la première version stockait le texte dans un attribut message de type string, sourcé depuis un simple <p>. La nouvelle version introduit un attribut niveau (info, alerte, erreur) absent de l’ancien markup. Voici la déprécation correspondante :
const v1 = {
attributes: {
message: {
type: 'string',
source: 'html',
selector: 'p',
},
},
save( { attributes } ) {
return <p>{ attributes.message }</p>;
},
migrate( attributes ) {
return {
...attributes,
niveau: 'info',
};
},
};
registerBlockType( 'wpmoderne/bandeau-alerte', {
// ...définition actuelle du bloc
deprecated: [ v1 ],
} );
Trois éléments composent chaque entrée du tableau deprecated : les attributes tels qu’ils existaient dans cette ancienne version, une fonction save() identique à celle de l’époque, et une fonction migrate() qui transforme les anciens attributs vers le format attendu par la version actuelle du bloc.
Le rôle d’isEligible
Dans certains cas, la structure du markup ne change pas, mais la logique de migration dépend d’une condition précise sur les attributs existants. La fonction optionnelle isEligible permet d’affiner ce déclenchement :
const v1 = {
// ...
isEligible( attributes ) {
return typeof attributes.niveau === 'undefined';
},
migrate( attributes ) {
return { ...attributes, niveau: 'info' };
},
};
Cette fonction est utile lorsque la déprécation doit s’appliquer même à un bloc dont le save() correspond déjà à la version actuelle, mais dont un attribut interne nécessite tout de même une correction silencieuse.
Empiler plusieurs déprécations
Un bloc ancien, régulièrement maintenu, accumule parfois plusieurs générations de markup. Le tableau deprecated accepte autant d’entrées que nécessaire, dans l’ordre du plus récent au plus ancien : Gutenberg les teste une par une jusqu’à trouver une correspondance.
- La version actuelle du bloc est testée en premier, via le
save()principal. - En cas d’échec, chaque entrée de
deprecatedest testée dans l’ordre déclaré. - Dès qu’une correspondance est trouvée,
migrate()s’exécute et le bloc est mis à jour de façon transparente, sans intervention de l’utilisateur.
Il n’est pas rare, sur un bloc vieux de plusieurs années, de trouver trois ou quatre déprécations empilées. Rien n’oblige à les supprimer : tant qu’elles restent correctes, elles ne coûtent rien en performance et garantissent que même le contenu le plus ancien reste éditable normalement.
Que se passe-t-il sans déprécation ?
Il est important de rassurer sur un point souvent mal compris : un bloc invalide dans l’éditeur ne casse jamais l’affichage côté front. Le HTML déjà enregistré en base continue de s’afficher normalement pour les visiteurs du site, puisqu’il est simplement injecté tel quel dans le flux de contenu. Le problème ne concerne que l’édition : l’auteur qui rouvre l’article voit un message d’erreur et ne peut plus modifier le bloc normalement tant que la situation n’est pas résolue.
Ne jamais publier un changement de save() sans déprécation associée, même pour un bloc que l’on pense peu utilisé. C’est justement le bloc oublié dans un vieil article que personne ne remarque cassé avant plusieurs mois.
En résumé
La propriété deprecated transforme un risque de rupture en simple détail d’implémentation invisible pour l’utilisateur final. Chaque modification du save() d’un bloc déjà publié devrait s’accompagner d’une entrée de déprécation correspondant à l’ancienne structure, avec une fonction migrate() qui adapte les attributs si nécessaire. C’est un peu de code supplémentaire à chaque évolution, mais c’est le prix à payer pour ne jamais casser le contenu de ses utilisateurs.