Voxfor - All rights reserved - 2013-2025
We Accepted





When updating Gutenberg blocks, maintaining Gutenberg Backward Compatibility ensures that existing content remains functional and visually consistent. This guide explains how to manage deprecated block versions, migrate attributes, and handle markup changes while preserving user content.
The deprecated array in registerBlockType() lets you define older versions of a block. The editor uses this to parse and render legacy content.
// Js Code
registerBlockType('my-plugin/my-block', {
// Current version
attributes: { title: { type: 'string' } },
save: ({ attributes }) => <h2>{attributes.title}</h2>,
// Deprecated versions
deprecated: [
{
// Version 1: Old attributes and save function
attributes: { heading: { type: 'string' } },
save: ({ attributes }) => <h3>{attributes.heading}</h3>,
migrate: (attributes) => ({ title: attributes.heading }),
},
],
});
Explanation:
When renaming or restructuring attributes, use migration functions to transform old data.
// JS Code
deprecated: [
{
attributes: { oldTitle: { type: 'string' } },
save: ({ attributes }) => <h3>{attributes.oldTitle}</h3>,
migrate: (attributes) => ({
title: attributes.oldTitle, // Map oldTitle to title
}),
},
]
// Js Code
// New: Store title as an object with text and color
attributes: {
title: {
type: 'object',
default: { text: '', color: 'black' },
},
},
// Old: Title was a string
deprecated: [
{
attributes: { title: { type: 'string' } },
save: ({ attributes }) => <h3>{attributes.title}</h3>,
migrate: (attributes) => ({
title: { text: attributes.title, color: 'black' },
}),
},
]
If the block HTML structure changes, provide deprecated save functions to parse old content.
// Js Code
// Current save function
save: ({ attributes }) => (
<div className="new-container">
<h2>{attributes.title}</h2>
</div>
),
// Deprecated version with old markup
deprecated: [
{
save: ({ attributes }) => (
<section className="old-container">
<h3>{attributes.title}</h3>
</section>
),
// Optional: Transform old HTML to new structure
__experimentalConvert: (domNode) => {
const title = domNode.querySelector('h3').textContent;
return {
title,
// New attributes can be added here
};
},
},
]
WordPress automatically validates blocks by comparing saved markup to the current save() output. If invalid, it checks deprecated versions for a match.
For complex HTML changes, use _experimentalConvert to transform old markup into new attributes.
// Js Code
deprecated: [
{
save: ({ attributes }) => <div class="old-class">{attributes.text}</div>,
__experimentalConvert: (domNode) => {
const text = domNode.querySelector('.old-class').textContent;
return { text };
},
},
]
List deprecations in reverse chronological order. The editor checks them sequentially.
// JS Code
deprecated: [
// Version 2 (recent)
{
attributes: { /* ... */ },
save: () => /* ... */,
migrate: (attrs) => /* ... */,
},
// Version 1 (oldest)
{
attributes: { /* ... */ },
save: () => /* ... */,
},
]
Use Jest and the @wordpress/block-editor package to test migrations:
// Js Code
import { createBlock } from '@wordpress/blocks';
test('migrates old attributes', () => {
const oldBlock = createBlock('my-plugin/my-block', { oldTitle: 'Hello' });
const migratedBlock = migrate(oldBlock);
expect(migratedBlock.attributes.title).toBe('Hello');
});
// Js Code
const BLOCK_VERSION = 3;
registerBlockType('my-plugin/my-block', {
attributes: { /* ... */ },
save: () => /* ... */,
deprecated: [
/* ... */
],
});
Scenario: A banner block initially stored text as a string but now supports subtitles and styles.
Step 1: Update Attributes
// Js Code
attributes: {
content: {
type: 'object',
default: { main: '', subtitle: '', color: 'blue' },
},
},
Step 2: Deprecate the Old Version
// Js Code
deprecated: [
{
attributes: { text: { type: 'string' } },
save: ({ attributes }) => <div class="banner">{attributes.text}</div>,
migrate: (attributes) => ({
content: { main: attributes.text, subtitle: '', color: 'blue' },
}),
},
]
Step 3: Test Migration
Implementing backward compatibility in Gutenberg blocks requires detailed planning, testing measures, and explicit documentation. Your block will enable user-friendly transitions by using the deprecated property with migration functions and validation workflows. This Process guarantee data reliability and user satisfaction while keeping trust and reliability as top priorities.
Hassan Tahir wrote this article, drawing on his experience to clarify WordPress concepts and enhance developer understanding. Through his work, he aims to help both beginners and professionals refine their skills and tackle WordPress projects with greater confidence.