Gutenberg Block Deprecation: Safely Updating Blocks Without Breaking Content

Gutenberg Block Deprecation

Gutenberg Block Deprecation is crucial —— when you want to update a Gutenberg block’s code — such as changing its HTML output or renaming attributes — older versions of that block in existing posts may no longer match your new structure. This can cause warnings like:

“This block contains unexpected or invalid content.”

To prevent this, Gutenberg provides a deprecated property in your block registration. It lets you define how the block used to work, so WordPress can still recognize and render old content properly.

Why Should Use Gutenberg Block Deprecation?

  • Keep old posts working after block updates
  • Avoid “invalid block” errors in the editor
  • Support smooth migration from older block versions
  • Improve content editing experience for users

How Does It Work?

You define one or more old versions of your block using the deprecated array.

Each version includes:

  • The old attributes
  • The old save() function
  • An optional migrate() function to convert old data to the new format

For instance, you have a simple notice block that used to save its output like this:

Old Block:

// save() output
<div class="notice-block">
  { attributes.message }
</div>

Block Attribute:

attributes: {
  message: { type: 'string' },
}

Now you want to update the block into the updated version :

  • Use a different class structure for styling
  • Rename message to content
  • Add a type attribute ('info', 'warning', 'success')

Updated attributes:

attributes: {
  content: { type: 'string' },
  type: { type: 'string', default: 'info' },
}

Updated save function:

save({ attributes }) {
  const { content, type } = attributes;
  return (
    <div className={`notice notice-${type}`}>
      <p>{content}</p>
    </div>
  );
}

Add a deprecated section:

Now, add the old version to a deprecated array:

const deprecated = [
  {
    attributes: {
      message: { type: 'string' },
    },
    save({ attributes }) {
      return (
        <div className="notice-block">
          {attributes.message}
        </div>
      );
    },
    migrate(attributes) {
      return {
        content: attributes.message,
        type: 'info',
      };
    },
  },
];

The final block registration:

registerBlockType('my-namespace/notice-block', {
  title: 'Notice Block',
  attributes: {
    content: { type: 'string' },
    type: { type: 'string', default: 'info' },
  },
  edit: MyEditComponent,
  save({ attributes }) {
    const { content, type } = attributes;
    return (
      <div className={`notice notice-${type}`}>
        <p>{content}</p>
      </div>
    );
  },
  deprecated: deprecated,
});

How this work?

  1. Blocks saved using the old format (message + .notice-block) are still recognized.
  2. WordPress uses the migrate() function to transform old attributes into the new schema (message → content, adds type: 'info').
  3. Avoids block errors or content loss for older posts.

Learn more about Gutenberg Block: Mastering Gutenberg Block Development: The Expert WordPress Developer’s Roadmap

Post a Comment