2026年5月31日

2026年5月31日

WordPressにGutenbergのカスタムブロックを追加する方法

はじめに

Gutenbergに独自のカスタムブロックを追加したい・@wordpress/scriptsでのビルド環境の設定がわからない・editsaveの違いが理解できない・ブロックを登録してもエディタに表示されないといった問題の解決方法を解説します。

症状・原因

  • block.jsoneditorScriptパスが間違っていてスクリプトが読み込まれない
  • save関数の出力が変わったが既存投稿のブロックが検証エラーになる
  • @wordpress/scriptsのビルドがエラーになりJSファイルが生成されない
  • registerBlockTypeの名前空間にスラッシュが含まれていない(myblockmyplugin/myblockが正しい)

解決手順

ステップ1:カスタムブロックの開発環境を構築する

# ✅ @wordpress/create-block でスキャフォールド
cd /var/www/html/wp-content/plugins/
npx @wordpress/create-block my-custom-block
cd my-custom-block

# ✅ 生成されたファイル構成を確認
ls -la
# → block.json
# → src/
# →   index.js     ← registerBlockType を呼び出すエントリーポイント
# →   edit.js      ← エディタ表示用コンポーネント
# →   save.js      ← フロントエンド保存用コンポーネント
# →   style.scss   ← フロントエンドのスタイル
# →   editor.scss  ← エディタのスタイル
# → package.json

# ✅ 依存関係をインストール
npm install

# ✅ 開発モードでビルド(ファイル変更を監視)
npm run start
# → Compiled successfully.

# ✅ 本番ビルド
npm run build
# → build/index.js  ← 圧縮されたJS
# → build/index.asset.php ← 依存関係リスト

# ✅ プラグインを有効化
wp plugin activate my-custom-block --path=/var/www/html/

ステップ2:block.jsonとregisterBlockTypeを設定する

// ✅ block.json
{
    "$schema": "https://schemas.wp.org/trunk/block.json",
    "apiVersion": 3,
    "name": "myplugin/my-custom-block",
    "version": "1.0.0",
    "title": "カスタムブロック",
    "category": "text",
    "icon": "star-filled",
    "description": "オリジナルのカスタムブロックです",
    "supports": {
        "html": false,
        "color": { "background": true, "text": true },
        "typography": { "fontSize": true }
    },
    "attributes": {
        "content": {
            "type": "string",
            "default": ""
        },
        "level": {
            "type": "number",
            "default": 2
        }
    },
    "editorScript": "file:./index.js",
    "editorStyle": "file:./index.css",
    "style": "file:./style-index.css"
}
// ✅ src/index.js
import { registerBlockType } from '@wordpress/blocks';
import './style.scss';
import Edit from './edit';
import save from './save';
import metadata from './block.json';

registerBlockType(metadata.name, {
    edit: Edit,
    save,
});

ステップ3:editとsaveコンポーネントを実装する

// ✅ src/edit.js(エディタ内の表示・編集UI)
import { useBlockProps, RichText, BlockControls } from '@wordpress/block-editor';
import { ToolbarGroup, ToolbarButton } from '@wordpress/components';
import { __ } from '@wordpress/i18n';

export default function Edit({ attributes, setAttributes }) {
    const blockProps = useBlockProps({
        className: 'my-custom-block',
    });
    const { content, level } = attributes;

    return (
        <>
            <BlockControls>
                <ToolbarGroup>
                    <ToolbarButton
                        label={__('見出しレベル', 'my-custom-block')}
                        onClick={() => setAttributes({ level: level === 2 ? 3 : 2 })}
                    >
                        H{level}
                    </ToolbarButton>
                </ToolbarGroup>
            </BlockControls>
            <div {...blockProps}>
                <RichText
                    tagName={`h${level}`}
                    value={content}
                    onChange={(value) => setAttributes({ content: value })}
                    placeholder={__('テキストを入力…', 'my-custom-block')}
                />
            </div>
        </>
    );
}
// ✅ src/save.js(フロントエンドへの保存出力)
import { useBlockProps, RichText } from '@wordpress/block-editor';

// save関数は変更するとブロック検証エラーになるため慎重に
export default function save({ attributes }) {
    const { content, level } = attributes;
    const blockProps = useBlockProps.save({
        className: 'my-custom-block',
    });
    return (
        <div {...blockProps}>
            <RichText.Content tagName={`h${level}`} value={content} />
        </div>
    );
}

ステップ4:PHPでブロックを登録する

// ✅ プラグインのメインPHPファイル(my-custom-block.php)
<?php
/**
 * Plugin Name: My Custom Block
 * Description: Gutenbergカスタムブロック
 * Version: 1.0.0
 */

// ✅ block.json からブロックを登録(推奨方法)
add_action('init', function() {
    register_block_type(__DIR__ . '/build');
    // → build/block.json を自動で読み込む
});

// ✅ 動的ブロック(PHPでレンダリング)の場合
add_action('init', function() {
    register_block_type(__DIR__ . '/build', [
        'render_callback' => function($attributes, $content) {
            $level = $attributes['level'] ?? 2;
            $text  = esc_html($attributes['content'] ?? '');
            return "<div class='my-custom-block'><h{$level}>{$text}</h{$level}></div>";
        },
    ]);
});

// ✅ ブロックカテゴリを追加
add_filter('block_categories_all', function($categories) {
    return array_merge([
        [
            'slug'  => 'my-blocks',
            'title' => 'My Custom Blocks',
            'icon'  => 'wordpress',
        ],
    ], $categories);
}, 10, 1);

ステップ5:ビルドエラーを解決してデプロイする

# ✅ よくあるビルドエラーを確認
npm run build 2>&1 | tail -20
# → Module not found: Error: Can't resolve '@wordpress/blocks'
# → 解決: npm install --save @wordpress/blocks

# ✅ @wordpress/scripts のバージョン確認
cat package.json | grep "@wordpress/scripts"
# → "@wordpress/scripts": "^26.0.0"

# ✅ webpack.config.js をカスタマイズ(複数エントリーポイントが必要な場合)
cat > webpack.config.js << 'EOF'
const defaultConfig = require('@wordpress/scripts/config/webpack.config');
module.exports = {
    ...defaultConfig,
    entry: {
        index: './src/index.js',
        'block-b': './src/block-b/index.js',
    },
};
EOF

# ✅ ビルドした資産をプラグインディレクトリにデプロイ
npm run build
ls build/
# → index.js  index.asset.php  style-index.css

# ✅ WP-CLIでブロックが登録されているか確認
wp eval "
\$registry = WP_Block_Type_Registry::get_instance();
\$block = \$registry->get_registered('myplugin/my-custom-block');
echo \$block ? 'Block registered: ' . \$block->name : 'Block NOT registered';
" --path=/var/www/html/
# → Block registered: myplugin/my-custom-block

注意事項

  • save関数の出力を変更すると既存の投稿でブロック検証エラーが発生します。既存ブロックに影響を与える変更が必要な場合はdeprecated配列に旧バージョンのsave関数を追加してください。edit関数は自由に変更できます
  • block.jsonnamenamespace/blocknameの形式(スラッシュを含む)でなければなりません。スラッシュがないとエラーになります

まとめ

Gutenbergカスタムブロックの作成は①npx @wordpress/create-blockでスキャフォールド・npm run startで開発ウォッチ・npm run buildで本番ビルド、②block.jsonに名前/カテゴリ/アイコン/attributes/editorScriptを設定・registerBlockType(metadata.name, {edit, save})でJSから登録、③edit.jsuseBlockProps/RichText/BlockControlsでエディタUIを実装・setAttributesで属性を更新、④save.jsRichText.Contentでフロントエンド出力を実装(変更すると検証エラーになるので慎重に)、⑤register_block_type(__DIR__ . '/build')でPHPから登録・動的ブロックにはrender_callbackを使用の手順で実装します。

お気軽にご相談ください

お見積りへ お問い合わせへ