2026年5月22日
2026年5月22日
WordPressのGutenbergブロックエラーを解決する方法
はじめに
WordPressのGutenbergブロックエディターで「このブロックにはエラーが発生しました」と表示される・register_block_type()でカスタムブロックを登録したのにエディターに表示されない・block.jsonのassets(JS/CSS)が読み込まれない・ブロックを保存すると「保存されたマークアップが無効です」エラーになるといった問題は、ブロックAPIの仕様とedit/save関数の整合性を正しく理解することで解決できます。
症状・原因
register_block_type()をinitフック外で呼び出しているか、block.jsonのパスが間違っているedit関数とsave関数の出力するHTMLが一致しないため「無効なマークアップ」エラーが発生している- JavaScriptの
registerBlockTypeでblock nameの名前空間(namespace/block-name形式)が正しくない - ブロックのスクリプトに
wp-blocks・wp-elementなどの依存関係がwp_enqueue_scriptの依存配列に含まれていない
解決手順
ステップ1:ブロックの状態を診断する
# 登録済みブロックを確認
wp eval "print_r(array_keys(WP_Block_Type_Registry::get_instance()->get_all_registered()));" | grep myplugin
# ブロックのアセットが正しくエンキューされているか確認
wp eval "
global \$wp_scripts;
foreach (\$wp_scripts->queue as \$handle) {
if (strpos(\$handle, 'myplugin') !== false) {
echo \$handle . ': ' . \$wp_scripts->registered[\$handle]->src . PHP_EOL;
}
}
"
# block.json の存在確認
ls -la wp-content/plugins/my-plugin/build/block.json
# ブラウザコンソールでエラーを確認(開発者ツール)
# Uncaught Error: Block "myplugin/my-block" is not registered.
ステップ2:block.jsonとPHP登録を正しく設定する
// block.json(ブロック定義ファイル)
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "myplugin/my-card",
"version": "1.0.0",
"title": "マイカードブロック",
"category": "common",
"icon": "index-card",
"description": "カード形式でコンテンツを表示するブロック",
"supports": {
"html": false,
"align": ["wide", "full"],
"color": {
"background": true,
"text": true
}
},
"attributes": {
"title": {
"type": "string",
"default": ""
},
"content": {
"type": "string",
"source": "html",
"selector": ".card-content"
},
"imageId": {
"type": "integer",
"default": 0
}
},
"editorScript": "file:./index.js",
"editorStyle": "file:./index.css",
"style": "file:./style-index.css"
}
// PHP側でblock.jsonを使って登録
add_action('init', function(): void {
// ✅ block.json があるディレクトリを渡す(ファイルパスではない)
register_block_type(__DIR__ . '/build');
// または複数ブロックをまとめて登録
$blocks = ['my-card', 'my-slider', 'my-accordion'];
foreach ($blocks as $block) {
register_block_type(__DIR__ . "/build/{$block}");
}
});
// サーバーサイドレンダリングが必要なブロック
add_action('init', function(): void {
register_block_type(__DIR__ . '/build', [
'render_callback' => function(array $attributes, string $content): string {
$title = esc_html($attributes['title'] ?? '');
$posts = get_posts([
'numberposts' => (int) ($attributes['count'] ?? 3),
'post_status' => 'publish',
]);
$output = "<div class='dynamic-block'><h2>{$title}</h2><ul>";
foreach ($posts as $post) {
$output .= '<li><a href="' . esc_url(get_permalink($post)) . '">'
. esc_html($post->post_title) . '</a></li>';
}
return $output . '</ul></div>';
},
]);
});
ステップ3:JavaScriptのedit/save関数を正しく実装する
// src/index.js
import { registerBlockType } from '@wordpress/blocks';
import { useBlockProps, RichText, InspectorControls } from '@wordpress/block-editor';
import { PanelBody, TextControl } from '@wordpress/components';
import metadata from './block.json';
registerBlockType(metadata.name, {
edit: function Edit({ attributes, setAttributes }) {
// ✅ useBlockProps() は必ず呼ぶ(ブロックのクラス・属性を付与)
const blockProps = useBlockProps({
className: 'my-card-editor',
});
return (
<>
<InspectorControls>
<PanelBody title="カード設定">
<TextControl
label="タイトル"
value={attributes.title}
onChange={(title) => setAttributes({ title })}
/>
</PanelBody>
</InspectorControls>
<div {...blockProps}>
<RichText
tagName="h3"
value={attributes.title}
onChange={(title) => setAttributes({ title })}
placeholder="タイトルを入力..."
/>
<RichText
tagName="div"
className="card-content"
value={attributes.content}
onChange={(content) => setAttributes({ content })}
placeholder="コンテンツを入力..."
/>
</div>
</>
);
},
// ✅ save の出力は edit と完全に一致させる
save: function Save({ attributes }) {
const blockProps = useBlockProps.save({
className: 'my-card',
});
return (
<div {...blockProps}>
<h3>{attributes.title}</h3>
<RichText.Content
tagName="div"
className="card-content"
value={attributes.content}
/>
</div>
);
},
});
ステップ4:ブロックの「無効なマークアップ」エラーを修正する
// deprecated(非推奨版)でマークアップ変更の後方互換性を保つ
registerBlockType('myplugin/my-card', {
// ... edit function ...
save: function Save({ attributes }) {
// 現在の save 関数(v2)
const blockProps = useBlockProps.save();
return (
<div {...blockProps}>
<h3 className="card-title">{attributes.title}</h3>
</div>
);
},
deprecated: [
{
// v1 の旧 save 関数(マークアップ変更前)
attributes: {
title: { type: 'string', default: '' },
},
save: function SaveV1({ attributes }) {
return (
<div className="my-card">
<h3>{attributes.title}</h3>
</div>
);
},
migrate: function migrate(attributes) {
// 旧属性を新属性に変換
return attributes;
},
},
],
});
# 無効になったブロックを一括で再保存(WP-CLI)
wp post list --post_type=post --format=ids | xargs -I{} wp post update {} --post_content="$(wp post get {} --field=post_content)"
ステップ5:ブロックのビルド環境を整える
# @wordpress/scripts でビルド環境を構築
npm install --save-dev @wordpress/scripts
# package.json に scripts を追加
# {
# "scripts": {
# "build": "wp-scripts build",
# "start": "wp-scripts start",
# "lint:js": "wp-scripts lint-js"
# }
# }
# 開発時(ファイル監視)
npm run start
# 本番ビルド(最小化)
npm run build
// ブロックのスクリプトをデバッグする
add_action('enqueue_block_editor_assets', function(): void {
// ブロックエディター専用スクリプトを手動エンキュー(block.json 未使用時)
wp_enqueue_script(
'myplugin-blocks',
plugins_url('build/index.js', __FILE__),
['wp-blocks', 'wp-element', 'wp-editor', 'wp-components', 'wp-i18n'],
filemtime(plugin_dir_path(__FILE__) . 'build/index.js')
);
wp_enqueue_style(
'myplugin-blocks-editor',
plugins_url('build/index.css', __FILE__),
['wp-edit-blocks'],
filemtime(plugin_dir_path(__FILE__) . 'build/index.css')
);
});
注意事項
save関数の出力を変更すると既存のブロックが「無効なマークアップ」エラーになります。deprecated配列に旧バージョンのsave関数を追加して後方互換性を維持してくださいregister_block_type()に渡すパスはblock.jsonが置かれているディレクトリパスです。ファイルパス(/build/block.json)ではなくディレクトリパス(/build)を渡してください
まとめ
WordPressGutenbergブロックエラーの解決は①WP_Block_Type_Registryで登録済みブロックを確認・ブラウザコンソールでJSエラーを確認・ブロックアセットのエンキュー状態を調査、②block.jsonにname/apiVersion/editorScript/styleを正しく定義・register_block_type(__DIR__.'/build')でディレクトリパスを渡す・SSR必要時はrender_callbackを追加、③useBlockProps()をedit/save双方で呼ぶ・RichText.Contentでsaveの出力を固定・InspectorControlsでサイドバーUIを実装、④deprecated配列に旧save関数を追加して後方互換を確保・migrate関数で旧属性を新属性に変換・WP-CLIで既存投稿を一括再保存、⑤@wordpress/scriptsでビルド環境を構築・npm run startで開発時ファイル監視・wp-blocks/wp-element/wp-editorを依存配列に追加の手順で解決します。