WordPress Logo WordPress ブロック開発の環境構築(Create Block ツールについての覚書)

WordPress の公式ツール Create Block を使って基本的なブロック開発の環境を構築する方法や複数ブロックを1つのプラグインとして作成する方法などについての覚書です。

更新日:2025年01月11日

作成日:2024年12月28日

Create Block ツールとは

Create Block はブロックの作成に必要なひな形と開発環境を構築する WordPress の公式ツールです。

ブロックのひな形とは、ブロックとして認識されるために必要なファイル(プラグインファイルや index.js、style.css など)を含むディレクトリ構造(初期構成)です。

ブロックの作成では JSX を使うため、JSX 構文をブラウザが理解できるように変換するための JavaScript ビルド環境が必要ですが、Create Block ツールは開発環境も同時に構築してくれます。

Create Block ツールを使ってブロックを開発するには以下が必要になります。

  • ローカル環境( XAMPP や MAMP、Local by Flywheel、wp-env など)
  • ターミナル
  • Node.js

以下ではすでにローカル環境と Node(NPM)がインストールされていることを前提にしています。

ローカル環境 関連ページ:

関連ページ

この時点での Create Block ツールのバージョンは 4.58.1 です。また、以下で使用している WordPress のバージョンは 6.7.1 です。

使い方(概要)

ブロックのひな型と開発環境を構築するには、ターミナルで create-block コマンドを実行します。

例えば、プラグインディレクトリで以下のコマンドを実行すると、my-block というディレクトリが作成され、その中に必要なファイルが生成されます。

% npx @wordpress/create-block@latest my-block

プラグインディレクトリの中に以下のようなブロックのディレクトリ my-block が作成されます。

create-block version 4.58.0 からは、src 及び build ディレクトリの中にブロックのサブフォルダが生成されるようになっています。

📁 my-block
├──📁 build
│   └──📁 my-block
│       ├── block.json
│       ├── index-rtl.css
│       ├── index.asset.php
│       ├── index.css
│       ├── index.js
│       ├── style-index-rtl.css
│       ├── style-index.css
│       ├── view.asset.php
│       └── view.js
├──📁 node_modules
├── my-block.php  // メインのプラグインファイル
├── package-lock.json
├── package.json
├── readme.txt
└──📁 src // 開発用のファイルが格納されたディレクトリ
    └──📁  my-block
        ├── block.json
        ├── edit.js
        ├── editor.scss
        ├── index.js
        ├── save.js
        ├── style.scss
        └── view.js

管理画面のプラグインページでプラグイン my-block を有効化します。

ターミナルでディレクトリ my-block に移動し、npm start コマンドを実行して開発を開始します。

% cd my-block
% npm start

npm start コマンドにより開発モード(Watch モード)になり、src ディレクトリのファイルを編集して保存すると、自動的に開発ビルドが実行され、変更が反映されます。

開発が完了したら、control + c で開発モードを終了し、npm run build コマンドで本番用にビルドを実行します。

% npm run build

以上が使い方の概要です。Create Block ツールの使い方自体はとても簡単です。

以下は、create-block コマンドのオプションや create-block コマンドを実行して生成されるファイルの概要、複数ブロックを1つのプラグインとして作成する方法などについての覚書です。

create-block コマンド

ブロックのひな型を生成して、ブロックの開発環境を構築するには create-block コマンド(@wordpress/create-block)を使います。以下が書式です。

% npx @wordpress/create-block@latest [options] [slug]

slug

slug にはひな形ファイルの出力先 (フォルダ名) を指定します。--title オプションを省略した場合、指定した値はプラグイン名やブロックの表示タイトルとしても使用されます。

例えば、slug に my-sample と指定すると my-sample という名前のディレクトリが作成され、プラグインの表示タイトルは My Sample になり、メインのプラグインファイル名は my-sample.php になります。

slug を省略すると、スクリプトは対話モードで実行され、ひな形プロジェクトに必要なオプションの入力 (slug、title、namespace…)を求めるプロンプトが表示されます。

options

options には以下のオプションを指定できます(省略した場合はデフォルト値が適用されます)。

category などの一部のオプションの設定は、後から変更することができます。

オプション 説明
-V, --version バージョン番号を出力。デフォルトは 0.1.0。
-t, --template <name> プロジェクトテンプレートタイプ名。指定可能な値: "static" (デフォルト)、"es5"、外部 npm パッケージ名、ローカルディレクトリへのパス。
--no-plugin ひな形ブロックファイルのみを作成します。
--namespace <value> ブロック名の内部名前空間。--namespace を省略した場合の名前空間の値は create-block になります。
--title <value> ブロックの表示タイトル及びプラグイン名。省略すると slug で指定した値が使用されて生成されます。
--short-description <value> ブロックと WordPress プラグインの短い説明。
--category <name> ブロックのカテゴリー名(text、media、design、widgets、theme、embed)。デフォルトは widgets。
--wp-scripts @wordpress/scripts パッケージとの統合を有効化。
--no-wp-scripts @wordpress/scripts パッケージとの統合を無効化。
--wp-env @wordpress/env パッケージとの統合を有効化。この引数を指定すると、プラグイン内で wp-env パッケージを実行するための構成やスクリプトを追加してくれるので、wp-env を使って WordPress ローカル環境を構築できます(Docker がインストールされている必要があります)。
-h, --help ヘルプの出力(以下に出力例があります)
--variant テンプレートで定義されたブロックのバリエーションを選択。ダイナミックブロックを生成するには --variant=dynamic を指定します。

オプションに -h または --help を指定して実行すると、オプションなどを確認することができます。

 % npx @wordpress/create-block -h
Usage: wp-create-block [options] [slug]

Generates PHP, JS and CSS code for registering a WordPress plugin with blocks.

[slug] is optional. When provided, it triggers the quick mode where it is used as the block slug used for its identification, the output location for scaffolded files, and the name of the WordPress plugin.The rest of the configuration is set to all default values unless overridden with some options listed below.

Options:
  -V, --version                output the version number
  -t, --template <name>        project template type name; allowed values: "standard", "es5", the name of an
                               external npm package, or the path to a local directory (default: "standard")
  --variant <variant>          the variant of the template to use
  --no-plugin                  scaffold only block files
  --target-dir <directory>     the directory where the files will be scaffolded, defaults to the slug
  --namespace <value>          internal namespace for the block name
  --title <value>              display title for the block and the WordPress plugin
  --short-description <value>  short description for the block and the WordPress plugin
  --category <name>            category name for the block
  --wp-scripts                 enable integration with `@wordpress/scripts` package
  --no-wp-scripts              disable integration with `@wordpress/scripts` package
  --wp-env                     enable integration with `@wordpress/env` package
  -h, --help                   display help for command

Examples:
  $ wp-create-block
  $ wp-create-block todo-list
  $ wp-create-block todo-list --template es5 --title "TODO List"

対話モード

slug を指定しないでコマンドを実行すると対話モードになります。表示されるそれぞれの問いに対して値を入力して return キーを押すことでオプションを設定することができます。

何も値を入力せず return キーを押せば、表示されるデフォルト値が設定されます。

対話モードで「Do you want to customize the WordPress plugin? 」の質問に対して「Yes」を選択すると、プラグインファイルのヘッダーフィールドの設定項目を指定することができます。「No」を選択すると、対話モードは終了しコマンドが実行されます。

対話モードで設定できるオプション
オプション 説明 デフォルト
variant 動的ブロック(ダイナミックブロック)を生成する場合、dynamic を選択 static
slug ファイルの出力先ディレクトリ名に使用される文字列 example-static
namespace 名前空間。ブロックをユニークに識別できる文字列 create-block
title プラグインの名前(プラグインヘッダの Plugin Name)及びブロックの表示タイトル Example Static
description ブロックの短い説明を指定。プラグインヘッダの Description。 Example block scaffolded with Create Block tool.
dashicon ブロックのアイコン。 smiley
category カテゴリー。text、media、design、widgets、theme、embed から選択 widgets
plugin URL プラグインのホームページ URL。
version プラグインヘッダに記載されるプラグインのバージョン 0.1.0
plugin author プラグインヘッダに記載されるプラグインの作者。 The WordPress Contributors
plugin's license プラグインヘッダに記載されるプラグインのライセンス(short name) GPL-2.0-or-later
link to license プラグインヘッダに記載されるライセンスの全文へのリンク https://www.gnu.org/licenses/gpl-2.0.html
Domain Path 翻訳のドメインパス
Update URI カスタムアップデート URI
textdomain ブロック内の文字列を翻訳可能にするために使用されるテキストドメイン(--no-plugin オプションを指定した場合)

これらのオプションは雛形のファイルを生成後、変更することができます。

create-block version 4.58.0 からは、対話モード(slug を省略)で --no-plugin オプションを指定した場合は、textdomain オプションを設定できるようになっています。

ブロックのひな型の作成

ブロックのひな形を作成するにはターミナルを開き、ブロックを作成するディレクトリに移動します。

これは通常、WordPress インストールの wp-content/plugins(プラグインディレクトリ)になります。

以下は WrodPress のインストールディレクトリでターミナルを開いて cd コマンドでプラグインディレクトリに移動しています。

% cd wp-content/plugins

create-block コマンドの書式は npx @wordpress/create-block@latest [options] [slug] です。

次のコマンドを入力し、return キーを押して実行します。

この例ではオプションは省略してスラッグに my-first-block を指定して、スタティック(静的)ブロックのひな型を作成します。

% npx @wordpress/create-block@latest my-first-block

上記を実行すると、plugins ディレクトリに my-first-block というフォルダが作成されその中にブロック構築に必要なファイルやディレクトリが出力されます(コマンドが完了するまでに少し時間がかかります)。

以下は実行例です。

コマンドのレスポンスには、開発に使用する npm start などのコマンドも表示されます。

もし、上記コマンドを実行して以下のようなコマンドをアップデートする表示が出たら y を入力して return キーを押すと更新がインストールされてからコマンドが実行されます。

Need to install the following packages:
  @wordpress/create-block@4.58.1
  Ok to proceed? (y) // y と入力して return キーを押す

--namespace オプション

この例では、create-block コマンドを実行する際に、--namespace を使って namespace を指定していませんが、実際の開発では namespace を指定した方が良いでしょう。

ブロックのファイル構成

plugins ディレクトリに作成されたブロックのディレクトリ my-first-block は以下のような構成です。

以下の3つのディレクトリが作成されています。

build ブロックの最終的なデプロイ可能なビルドが配置される場所です。開発用の src ディレクトリで編集したファイルをビルドすると自動的に必要なファイルがバンドルされてこのディレクトリに出力されます。デフォルトでは、この中の index.js がビルドされたブロック用のスクリプトです。
node_modules ビルドプロセスが依存するすべてのモジュールが配置されている場所です。言い換えると、開発環境の構築に必要なファイルが入っています。
src 開発で使用するファイルが格納されているディレクトリです。この中のファイルを使ってブロックを開発します。デフォルトでは、この中の index.js が ブロック用のメインのスクリプトです。ビルドを実行すると、ブラウザが理解できる構文に変換され、必要な関連ファイルと共に build ディレクトリに出力されます。

version 4.58.0 の変更点

create-block の version 4.58.0 からは、単一のプラグインで複数のブロックを簡単に作成できるように src 及び build ディレクトリの中に slug に指定した名前のサブフォルダが生成されるようになっています。

開発では src ディレクトリ内のファイルとプラグインファイル(my-first-block.php)を使用します。

通常、build と node_modules ディレクトリ内のファイルを編集(操作)することはありません。

[参考情報] ビルドには裏側で webpack が使われています。webpack の設定ファイル webpack.config.js は node_modules/@wordpress/scripts/config/ にあります。

また、ブロックのディレクトリ(my-first-block)の直下には以下のファイルが生成されています。

.editorconfig エディタや IDE のコーディングスタイルを統一するための設定ファイル
.gitignore Git バージョン管理にコミットされるコードを管理するためのファイル
my-first-block.php メインのプラグインファイル
package-lock.json インストールされたパッケージの依存パッケージが記載述されたファイル
package.json インストールされたパッケージに関する設定情報などが記述されたファイル
readme.txt 公式プラグインディレクトリ公開する場合に必要となるファイル。

上記ファイルで重要なのは、次項のプラグインファイル(my-first-block.php)と package.json です。

プラグインファイル

この例の場合、create-block コマンドの slug に my-first-block と指定したので、my-first-block.php という名前の PHP ファイルが自動的に生成されています。

この my-first-block.php はプラグインの実行を開始するメインのプラグインファイルです。

ファイルの先頭部分には、以下のようなコメントブロックが記述されています。これは WordPress がこのプラグインファイルとそのコンテンツをロードするために読み取るプラグインヘッダーです。

<?php
/**
 * Plugin Name:       My First Block
 * Description:       Example block scaffolded with Create Block tool.
 * Version:           0.1.0
 * Requires at least: 6.7
 * Requires PHP:      7.4
 * Author:            The WordPress Contributors
 * License:           GPL-2.0-or-later
 * License URI:       https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain:       my-first-block
 *
 * @package CreateBlock
 */

この例では create-block コマンドを実行する際に、slug を指定しただけなので Plugin Name(My First Block)と Text Domain(my-first-block)が slug の値をもとに自動的に設定されています。その他はデフォルトの値が設定されているので、必要に応じて変更します。

Plugin Name や Description、 Version、Author などの値は管理画面のプラグインページでプラグイン名やプラグインの説明部分に表示されます。

これらの情報は、create-block コマンドを実行する際に slug を指定せずに、対話モードで実行することで設定することもできます。

詳細:Header Requirements

プラグインヘッダーの後には以下のようなセキュリティ対策のコードが記述されています。

ABSPATH は WordPress がインストールされているディレクトリのフルパスが入っている定数です(wp-load.php と wp-config.php で定義されています)。

defined は指定した名前の定数が存在するかどうかを調べる関数です。もし、直接ファイルにアクセスされた場合は ABSPATH が定義されていないので、その場合は exit するようになっています。

if (! defined('ABSPATH')) {
  exit; // Exit if accessed directly.
}

セキュリティ対策のコードの後には以下のような init アクションにフックされる関数が記述されています。

関数の上のコメントには『`block.json` ファイルから読み込まれたメタデータを使用してブロックを登録します。バックグラウンドでは、すべてのアセットも登録されるため、対応するコンテキストでブロック エディターを介してキューに追加できます。』と書かれています。

この関数では register_block_type() 関数にブロックを定義するメタデータを含む block.json の場所(build/my-first-block へのパス)をパラメーターとして渡して、build/my-first-block ディレクトリの block.json ファイルに設定されたメタデータを読み込むことで、ブロックをサーバーに登録しています。

__DIR__ はそのファイルの存在するディレクトリのパスを返す PHP の定数です。

関数の名前(create_block_my_first_block_block_init)は namespace と slug(ブロック名)の文字列を使って自動的に生成されています。この例の場合、namespace を指定していないので、デフォルトの create-block が使われています。

詳細:ブロックの登録

/**
 * Registers the block using the metadata loaded from the `block.json` file.
 * Behind the scenes, it registers also all assets so they can be enqueued
 * through the block editor in the corresponding context.
 *
 * @see https://developer.wordpress.org/reference/functions/register_block_type/
 */

function create_block_my_first_block_block_init() {
  register_block_type( __DIR__ . '/build/my-first-block' ); // ブロックをサーバーに登録
}
add_action( 'init', 'create_block_my_first_block_block_init' );

register_block_type()

WordPress 5.8 以降、register_block_type 関数は、第1引数に block.json ファイルが置かれているフォルダ(build ディレクトリ内のブロックのフォルダ)へのパスを指定することで、block.json ファイルからメタデータを読み取ってブロックタイプをサーバーに登録できるようになっています。

パフォーマンスに関しては、テーマがアセットの遅延読み込みをサポートしている場合、block.json を使用して登録されたブロックのアセットエンキューは自動的に最適化されます。

具体的には、block.json の style や script、editorScript プロパティなどで指定されたリソースが、ブロックが検出されたときにのみフロントエンドにエンキューされるため、不要な読み込みが減り、ページサイズが削減されます。

詳細:Block API Enhancements in WordPress 5.8

package.json

package.json は WordPress 固有のものではなく、インストールされたパッケージに関する依存関係などが記述された npm のファイルです。

依存関係とは、プロジェクトを適切に実行するために必要な外部パッケージまたはモジュールです。この場合、必要な依存関係は、devDependencies にリストされている @wordpress/scripts パッケージの開発依存関係のみです。これらの依存関係は、node_modules ディレクトリにインストールされます。

また、package.json の scripts フィールドには開発時やビルドの際に使用できるコマンド(npm scripts)が登録されています。

npm run に続けて scripts フィールドのキー名を指定して実行すると登録されているスクリプトが実行されます。例えば、build を指定して npm run build で npx wp-scripts build を実行できます。

{
  "name": "my-first-block",
  "version": "0.1.0",
  "description": "Example block scaffolded with Create Block tool.",
  "author": "The WordPress Contributors",
  "license": "GPL-2.0-or-later",
  "main": "build/index.js",
  "scripts": {
    "build": "wp-scripts build",
    "format": "wp-scripts format",
    "lint:css": "wp-scripts lint-style",
    "lint:js": "wp-scripts lint-js",
    "packages-update": "wp-scripts packages-update",
    "plugin-zip": "wp-scripts plugin-zip",
    "start": "wp-scripts start"
  },
  "devDependencies": {
    "@wordpress/scripts": "^30.8.1"
  }
}

src ディレクトリ

src ディレクトリには開発用のファイルが格納されています。

create-block version 4.58.0 未満では src ディレクトリの直下に開発用のファイルが配置されていましたが、4.58.0 以降では src ディレクトリの中にブロックのサブフォルダ(この例では my-first-block)が作成され、その中にファイルが配置されています。

ビルドを実行すると、React コンポーネントの JSX などがブラウザが理解できる構文に変換され、必要な関連ファイルと共に build ディレクトリに出力されます。

この例では --variant オプション(--variant=dynamic)を指定していないので、スタティックブロック(静的ブロック)のひな型が生成されています。

参考:ブロックのファイル構成(日本語ドキュメント)

block.json

block.json には、JSON オブジェクトとして定義されたブロックのメタデータが格納されます。

このファイルでは、edit.js と save.js で定義された関数がパラメーターとして使用できる属性(attributes)やブロックサポート(supports)などを定義します。

以下は自動的に生成された block.json です。

{
  "$schema": "https://schemas.wp.org/trunk/block.json",
  "apiVersion": 3,
  "name": "create-block/my-first-block",
  "version": "0.1.0",
  "title": "My First Block",
  "category": "widgets",
  "icon": "smiley",
  "description": "Example block scaffolded with Create Block tool.",
  "example": {},
  "supports": {
    "html": false
  },
  "textdomain": "my-first-block",
  "editorScript": "file:./index.js",
  "editorStyle": "file:./index.css",
  "style": "file:./style-index.css",
  "viewScript": "file:./view.js"
}

4行目の name プロパティの値は create-block/my-first-block となっていますが、これは namespace にデフォルトの create-block が適用されているためです。name プロパティの構造は namespace/block-name となっています(block-name は slug の値)。

textdomain プロパティは国際化対応(翻訳)で使用します。デフォルトでは create-block コマンドの slug に指定した値が使われます。

editorScript、editorStyle、style プロパティは、フロントエンドとバックエンドのスクリプトとスタイルへの相対パスが自動的に設定されています。ここで定義されたスクリプトとスタイルは WordPress によって自動的に登録され、キューに入れられるため、手動で登録する必要はありません。

必要に応じて category や icon、description などを編集します

namespace や category、icon、description などは create-block コマンドを実行する際にオプションや対話モードであらかじめ設定することができます。

これらの値は編集画面のインサーターやブロックを選択した際にブロックの情報として表示されます。

category はインサーターで表示される場所(カテゴリー)を指定します。デフォルトは widgets なので、ウィジェットカテゴリーの下に表示されます。

icon には WordPress Dashicons のアイコンを指定できます(アイコン名から dashicons- を除いた値)。

挿入後、ブロックが選択されている場合もサイドバーにブロックの情報として表示されます。

参考:block.json のメタデータ

edit.js

edit.js はブロックがどのように機能し、どのようにエディターに表示されるかを制御するファイルです。

以下は自動的に生成された block.json です。元のコメントは削除してあります。

エディター内でブロックがどのように表示され、機能するかを決定する React コンポーネント Edit をエクスポートしています。Edit コンポーネントは index.js ファイルの registerBlockType 関数の edit プロパティに渡されます。

このファイルで、ブロックのマークアップやインスペクターパネルに表示されるコントロールなどを定義します。

ここで定義される Edit() は通常、block.json で定義された属性(attributes)や setAttributes などのメソッドを含むオブジェクト(props)をパラメーターとして受け取りますが、生成されたひな型のファイルでは attributes を設定していないのでパラメータには何も受け取っていません。

2行目でインポートしている __ はテキストの翻訳を取得する関数で、__( text, textdomain ) の形式で使用します(14行目)。

// 翻訳テキストを取得する関数 __ をインポート
import { __ } from '@wordpress/i18n';
// ブロックラッパー要素に展開して必要なプロパティを提供する useBlockProps(React フック)をインポート
import { useBlockProps } from '@wordpress/block-editor';
// エディター用スタイルをインポート
import './editor.scss';

// Edit 関数(コンポーネント)をエクスポート
export default function Edit() {
  // p 要素をレンダリングする JSX を返す
  return (
    // ラッパー要素に useBlockProps() を展開して、エディターで必要とされる属性やクラスなどを出力
    <p { ...useBlockProps() }>
      { __( 'My First Block – hello from the editor!', 'my-first-block' ) }
    </p>
  );
}

上記では削除していますが、自動的に生成された元のファイルにはコメントとしてコードの説明が記述されています。

/**
* Retrieves the translation of text.
*
* @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-i18n/
*/
import { __ } from '@wordpress/i18n';

/**
* React hook that is used to mark the block wrapper element.
* It provides all the necessary props like the class name.
*
* @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/#useblockprops
*/
import { useBlockProps } from '@wordpress/block-editor';

/**
* Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.
* Those files can contain any CSS code that gets applied to the editor.
*
* @see https://www.npmjs.com/package/@wordpress/scripts#using-css
*/
import './editor.scss';

/**
* The edit function describes the structure of your block in the context of the
* editor. This represents what the editor will render when the block is used.
*
* @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-edit-save/#edit
*
* @return {Element} Element to render.
*/
export default function Edit() {
  return (
    <p { ...useBlockProps() }>
      { __(
        'My First Block – hello from the editor!',
        'my-first-block'
      ) }
    </p>
  );
}
useBlockProps

4行目でインポートしている useBlockProps(React フック)は、ラッパー要素(上記では p 要素)で {...useBlockProps()} のようにスプレッド演算子と共に使用すると block.json ファイルで定義された attributes を含むブロックの動作に必要な属性とクラスやイベントハンドラがラッパー要素に挿入されます(13行目)。

通常、ブロックのラッパー要素に {...useBlockProps()} を指定して必要な属性を展開します。

この例の場合、{ ...useBlockProps() } によりラッパーの p 要素には以下のような属性が展開されます。

<p tabindex="0" class="block-editor-block-list__block wp-block is-selected wp-block-create-block-my-first-block" id="block-c74d9b46-667e-4066-873f-424c88e0bceb" role="document" aria-label="ブロック: My First Block" data-block="c74d9b46-667e-4066-873f-424c88e0bceb" data-type="create-block/my-first-block" data-title="My First Block">My First Block – hello from the editor!</p>

ラッパー要素(ブロックラッパー)に追加のカスタム HTML 属性が必要であれば、属性を定義するオブジェクトを useBlockProps() に引数として渡して追加することもできます。

例えば、以下のように style 属性のオブジェクトを渡すと、上記の属性に加えて style="background-color: red;" が p 要素に追加されます。

<p { ...useBlockProps({ style: {backgroundColor: 'red'} }) }>

上記は以下とほぼ同じことです。

<p { ...useBlockProps() } style={ { backgroundColor: 'red' } } >

但し、以下のように記述すると、後から指定した style 属性で useBlockProps() に渡された style が上書きされ、backgroundColor は適用されません。

<p { ...useBlockProps({ style: {backgroundColor: 'red'} }) }  style={ { color: 'yellow' } } >;

クラス属性を追加する場合は、例えば、以下のようにクラス属性を表すオブジェクト className を useBlockProps() に渡します。

<p { ...useBlockProps({ className: 'foo' }) } >

これにより展開されるクラス属性に foo が追加されます。

<p tabindex="0" class="block-editor-block-list__block wp-block is-selected foo wp-block-create-block-my-first-block" id="block-b32a52af-daba-446d-8f5f-2bf1cc100cb0" role="document" aria-label="ブロック: My First Block" data-block="b32a52af-daba-446d-8f5f-2bf1cc100cb0" data-type="create-block/my-first-block" data-title="My First Block">My First Block – hello from the editor!</p>

但し、以下のように記述すると、後から指定したクラス属性で useBlockProps() により展開されるブロックの動作に必要なクラス属性が上書きされてしまい、ブロックが正しく機能しません。

<p { ...useBlockProps() } className='foo'>

上記の場合、出力は以下のようになります。

<p tabindex="0" class="foo" id="block-2c5c967c-c383-44f5-a12a-90581e990f48" role="document" aria-label="ブロック: My First Block" data-block="2c5c967c-c383-44f5-a12a-90581e990f48" data-type="create-block/my-first-block" data-title="My First Block">My First Block – hello from the editor!</p>

参考:

editor.scss

editor.scss は、ブロックエディターでのブロックの外観をスタイルする CSS を含む Sass ファイルで、多くはブロックのユーザーインターフェイスに特化したスタイルに使用されます。

エディターでブロックをフロントエンドとは異なるスタイルで表示したい場合に使用します。

CSS を記述できますし、必要に応じて Sass 記法を使って記述することができます。

このファイルはビルド時に index.css に変換されます。また、create-block により自動的に block.json の editorStyle プロパティに index.css が指定されています。

以下は自動的に生成された editor.scss です。

エディターでブロックが選択されたときにオレンジ色の点線の枠線(border)を追加しています。

.wp-block-create-block-my-first-block {
  border: 1px dotted #f00;
}

ブロックのクラス名

上記では CSS のセレクターに .wp-block-create-block-my-first-block というクラスが使われています。

ブロックのラッパー要素には wp-block-{block-name} というクラスが追加されます。

{block-name} の部分は block.json の name プロパティの値 create-block/my-first-block のスラッシュをハイフンに置き換えた create-block-my-first-block になります。

editor.scss を削除

ブロックの表示をエディターとフロントエンドで同じにする場合、editor.scss は不要なので削除することができます。

但し、削除する場合(ファイルを削除する前に)、block.json で editorStyle プロパティの行を削除し、edit.js で editor.scss のインポートを削除します。

index.js

index.js はブロックの JavaScript 実行の開始点(エントリーポイント)です。

index.js では @wordpress/blocks パッケージの registerBlockType を使用して JavaScript でブロックをクライアントサイドに登録します。

registerBlockType の第1引数には、ブロック名(metadata.name)を指定し、第2引数にはブロックの構成オブジェクト(ブロックのプロパティ)を指定して実行します。

第1引数のブロック名は、10行目で block.json からインポートしたメタデータ metadata の name プロパティを参照しています。

第2引数の構成オブジェクトでは edit プロパティに edit.js からインポートした Edit コンポーネントを、save プロパティに save.js からインポートした save 関数を指定します。

// ブロックを登録する関数 registerBlockType をインポート
import { registerBlockType } from '@wordpress/blocks';
// フロントエンドとエディターの両方に適用されるスタイルをインポート(ビルド時に webpack が処理)
import './style.scss';
// edit.js から Edit コンポーネントをインポート
import Edit from './edit';
// save.js から save 関数をインポート
import save from './save';
// block.json からメタデータをインポート
import metadata from './block.json';

registerBlockType( metadata.name, {
  // edit プロパティに Edit コンポーネントを指定
  edit: Edit,
  // save プロパティに save 関数を指定
  save, // save: save, と同じこと(短縮構文)
} );

ブロック登録 API リファレンス:登録

save.js

save.js は、関数 save() をエクスポートします。

save() 関数は、投稿または固定ページが保存されるときにデータベースの wp_posts テーブルの post_content フィールドに保存されるマークアップを決定し、フロントエンドでのブロックの表示方法と機能を決定します。

edit.js と同様に、ここで定義される関数は通常、block.json で定義された属性(attributes)を含むオブジェクトをパラメーターとして受け取ります。

また、ブロックのラッパー要素に useBlockProps.save() をスプレッド演算子で展開します。これによりブロックサポート API からの任意の HTML 属性に加え、ブロッククラス名が正しくレンダーされます。

この関数は index.js ファイル内の registerBlockType 関数の save プロパティに渡されます。

以下は自動的に生成された save.js です。

//ブロックラッパー要素に展開して必要なプロパティを提供する useBlockProps(React フック)をインポート
import { useBlockProps } from '@wordpress/block-editor';

// save 関数をエクスポート
export default function save() {
  // p 要素をレンダリングする JSX を返す
  return (
    // ラッパー要素に useBlockProps().save() を展開して必要とされる属性やクラスなどを出力
    <p { ...useBlockProps.save() }>
      { 'My First Block – hello from the saved content!' }
    </p>
  );
}
style.scss

style.scss はブロックエディターとフロントエンドの両方に読み込まれる CSS を含む Sass ファイルです。

editor.scss 同様、必要に応じて Sass 記法が使えます。

エディター内でブロックを異なるように表示する必要がある場合は、ここでのスタイルを editor.scss のスタイルで上書きできます。

このファイルはビルドプロセスで style-index.css に変換されます。また、create-block により自動的に block.json の style プロパティに style-index.css が指定されています。

以下は自動的に生成された style.scss です。

.wp-block-create-block-my-first-block {
  background-color: #21759b;
  color: #fff;
  padding: 2px;
}

ブロックのラッパー要素には wp-block-{block-name} というクラスが追加され、 {block-name} は block.json の name プロパティの値(create-block/my-first-block)のスラッシュをハイフンに変えたもの(create-block-my-first-block)になります。

view.js

view.js は、ブロックが表示されるときにフロントエンドに読み込まれる JavaScript です。

以下は自動的に生成された view.js です。コンソールへの出力が記述されています。

console.log( 'Hello World! (from create-block-my-first-block block)' );

view.js を削除

フロントエンドに読み込む JavaScript が不要な場合は削除します。

その場合、block.json で viewScript プロパティの行(viewScript": "file:./view.js")を削除します。

プラグインの有効化

create-block コマンドを実行してブロックのひな形を作成した場合、そのプロセスによってビルド済みバージョンがすでに提供されているので、WordPress 管理画面のプラグインページに移動すると、プラグインがすでに有効化できる状態になっています。

上記プラグインページに表示されているプラグインの名前はプラグインファイル(my-first-block.php)のプラグインヘッダーに記載されている Plugin Name の値に、説明は Description の値になっています。

<?php
/**
* Plugin Name: My First Block
* Description: Example block scaffolded with Create Block tool.
...
*/

必要に応じてプラグインファイルを編集して変更することができます。

「有効化」をクリックして、プラグインを有効化します。

投稿に作成したブロックを挿入して確認します。検索ボックスに my などと入力すると作成した My First Block が表示されるので選択します。

またはインサーターの「ウィジェット」カテゴリーに表示されるので、そこから選択することもできます。

インサーターでブロックのアイコンにマウスオーバーするとブロックの情報とプレビューが表示されます。

投稿の編集画面でのブロックのタイトルや説明、アイコンはそれぞれ block.json の title や icon、description プロパティに設定されている値が適用されています。

ブロックがインサーターで表示される場所は、category プロパティに設定されている値 widgets が適用され、ウィジェットの下に表示されています。また、アイコンにマウスオーバーするとプレビューや情報が表示されるのは、example プロパティの指定(空のオブジェクト)によります。

{
  ...
  "title": "My First Block",
  "category": "widgets",
  "icon": "smiley",
  "description": "Example block scaffolded with Create Block tool.",
  "example": {},
  ...
}

ブロックを挿入するとエディターでは以下のように表示されます。サイドバーに表示されているブロックの情報は上記同様、block.json に指定されているプロパティの値です。

ここで表示されるテキストは、src/edit.js の以下の4行目に対応しています。

export default function Edit() {
  return (
    <p { ...useBlockProps() }>
      { __( 'My First Block – hello from the editor!','my-first-block' ) }
    </p>
  );
}

スタイルは src/style.scss と src/editor.scss が適用されています。

.wp-block-create-block-my-first-block {
  background-color: #21759b;
  color: #fff;
  padding: 2px;
}
.wp-block-create-block-my-first-block {
  border: 1px dotted #f00;
}

フロントエンド側は、例えば以下のように表示されます。

ここで表示されるテキストは、src/save.js の以下の4行目に対応しています。

export default function save() {
  return (
    <p { ...useBlockProps.save() }>
      { 'My First Block – hello from the saved content!' }
    </p>
  );
}

スタイルは src/style.scss が適用されています。

.wp-block-create-block-my-first-block {
  background-color: #21759b;
  color: #fff;
  padding: 2px;
}

プラグイン(ブロック)の削除

管理画面のプラグインページでプラグインを無効化して削除すると、ブロックのディレクトリ(とその中の build や src ディレクトリを含む全てのファイル)が削除されます。

削除したブロックのファイルは復元できないので注意が必要です。

開発関連コマンド

ブロックの開発は src ディレクトリのファイル(及びプラグインファイル)を編集して行います。

但し、ブロックはプラグインファイル my-first-block.php の register_block_type() 関数で、build ディレクトリをパラメーターとして受け取って登録されているので、src ディレクトリの変更を検出しません。

また、JSX や Sass はブラウザが理解できるように変換される必要があるため、src ディレクトリの変更を行ったらビルドを行う必要があります(詳細:ブロックエディターでの JavaScript の利用)。

create-block コマンドを実行してブロックのひな形を作成する際に、レスポンスに以下のような実行可能なコマンドのリストが表示されます。

You can run several commands inside:

  $ npm start  // 開始コマンド
    Starts the build for development.

  $ npm run build  // ビルドコマンド
    Builds the code for production.

  $ npm run format
    Formats files.

  $ npm run lint:css
    Lints CSS files.

  $ npm run lint:js
    Lints JavaScript files.

  $ npm run plugin-zip
    Creates a zip file for a WordPress plugin.

  $ npm run packages-update
    Updates WordPress packages to the latest version.

To enter the directory type:

  $ cd my-first-block

You can start development with:

  $ npm start

これらのコマンドは、package.json の scripts で定義されている以下の項目に対応しています。

{
  ...
  "scripts": {
    "build": "wp-scripts build",
    "format": "wp-scripts format",
    "lint:css": "wp-scripts lint-style",
    "lint:js": "wp-scripts lint-js",
    "packages-update": "wp-scripts packages-update",
    "plugin-zip": "wp-scripts plugin-zip",
    "start": "wp-scripts start"
  },
  ...
}

開始コマンドとビルドコマンド

上記のコマンドのうちよく使用するコマンドは以下の2つです。

npm start src ディレクトリ内のファイルを監視するローカル開発プロセスを開始し、それらのファイルに変更が加えられたときにビルドプロセス(development ビルド)を実行します。
npm run build src ディレクトリ内のすべてのコードを取得し、ブロックの最終的な配布可能なビルド(production ビルド)を作成します。

※ これらのコマンドはブロックのディレクトリで行う必要があるので、まず、ターミナルでブロックのディレクトリに移動しておく必要があります。

npm run build

例えば、以下のように src/style.scss で背景色を変更して保存します。

.wp-block-create-block-my-first-block {
  background-color: #d5341e; /* 背景色を変更 */
  color: #fff;
  padding: 2px;
}

但し、エディターやフロントエンドを確認すると、背景色は変わっていません。

まず、ターミナルでブロックのディレクトリに移動します。

% cd my-first-block

続いてビルドコマンド npm run build を実行します。

% npm run build

npm run build を実行すると以下のようなレスポンスが表示されてコマンドが終了し、コマンドプロンプトが戻ります。

そして src ディレクトリのファイルがビルドされて build ディレクトリに出力されます。

その結果、変更がサイトに反映されます。例えばエディターを確認すると以下のように背景色が変わっています。

通常、npm run build コマンドは最終の配布用(production ビルド)としてビルドする際に使用します。

npm run build コマンドにより出力されるファイルは圧縮されます。以下は build/index.js の例です。

本願環境で必要なファイル

create-block コマンドで生成されたブロックのディレクトリには、開発用のファイルの入った src ディレクトリや開発環境に必要なファイルの入った node_modules ディレクトリが含まれていますが、実際にプラグインが機能するのに必要なのは build ディレクトリとプラグインファイルになります。

my-first-block
├── build
│   ├── block.json
│   ├── index-rtl.css
│   ├── index.asset.php
│   ├── index.css
│   ├── index.js
│   ├── style-index-rtl.css
│   ├── style-index.css
│   ├── view.asset.php
│   └── view.js
└── my-first-block.php

上記のファイルを本番環境(サーバー)のプラグインディレクトリにアップロードすることもできますが、plugin-zip コマンドを使うと上記のファイルを zip 形式のプラグインファイルとして生成してくれます。

npm start

npm run build コマンドを実行すると、src ディレクトリ内のファイルが build ディレクトリにコンパイルされ、変更をブラウザーで確認できまます。

但し、コードに変更を加えるたびに、その変更結果をブラウザーで確認するためにビルドコマンドを実行するのは面倒です。そのため、開発中は npm start コマンドを使います。

npm start コマンドを実行すると「development ビルド」を build ディレクトリに 出力し、待機してファイルの変更を監視します。

ブロックのディレクトリで以下を実行します。

% npm start

上記コマンドを実行すると、ターミナルにレスポンスが表示され、最後にコンパイルが成功したことを示す行(例:webpack 5.97.1 compiled successfully in 1075 ms)が表示されます。

但し、npm run build コマンドを実行したときとは異なり、コマンドプロンプトは戻りません。この場合、プロセスは実行を継続し、src ディレクトリ内のファイルへの変更を監視し続けます(watch モード)。

そして、src フォルダ内のファイルが更新(変更して保存)されるたびに自動的にリビルドします。そのため、ファイルを変更するたびにコマンドを実行する必要はありません。

例えば、src/edit.js の出力する文字列を変更して保存すると、自動的にコンパイル(ビルド)され、その変更をブラウザで確認することができます。

また、npm run build コマンドによりコンパイルされたファイルは圧縮されますが、npm start コマンドの場合、圧縮されません。以下は build/index.js の例です。

終了(停止)

npm start コマンドを終了(開発を一時的に停止)するには control + c を押します。

再開するには再度 npm start を実行します。

npm run plugin-zip

開発が終了して最終的なビルドを実行したら、ターミナルで npm run plugin-zip コマンドを使って、作成したブロックの zip ファイルを作成することができます。

ブロックのディレクトリで npm run plugin-zip コマンドを実行します。

% npm run plugin-zip

実行すると、例えば以下のように、zip ファイルに含まれるファイルがレスポンスに表示され、zip ファイルがプロジェクトのルートディレクトリに生成されます。

デフォルトでは、プラグインファイルと build ディレクトリのファイル、及び readme.txt、もしあれば言語ディレクトリ(languages)が含まれます。

% npm run plugin-zip

> my-first-block@0.1.0 plugin-zip
> wp-scripts plugin-zip

Creating archive for `my-first-block` plugin... 🎁

Using Plugin Handbook best practices to discover files:

  Adding `my-first-block.php`.
  Adding `readme.txt`.
  Adding `build/block.json`.
  Adding `build/index-rtl.css`.
  Adding `build/index.asset.php`.
  Adding `build/index.css`.
  Adding `build/index.js`.
  Adding `build/style-index-rtl.css`.
  Adding `build/style-index.css`.
  Adding `build/view.asset.php`.
  Adding `build/view.js`.

Done. `my-first-block.zip` is ready! 🎉

zip ファイルを使ってブロックをインストール

生成された zip ファイルを使えば、作成したブロックをプラグインとして本願環境や他のサイトにインストールすることができます。

本願環境や他のサイトでブロックを zip ファイルからインストールするには、ダッシュボードのプラグイン画面で、「新規プラグインを追加」をクリックします。

「プラグインをアップロード」をクリックします。

「ファイルを選択」をクリックして、作成した zip ファイルを選択します。

以下では生成されたフォルダを参照していますが、zip ファイルはどこに保存しておいても大丈夫です。

zip ファイルを選択したら、「今すぐインストール」をクリックします。

問題なくインストールされると以下のように表示されるので「プラグインを有効化」をクリックして有効化します。

zip ファイルに src フォルダも含める

デフォルトでは npm run plugin-zip を実行すると src フォルダのファイルは含まれません。

src フォルダのファイルも含めたい場合は、package.json に files フィールドの行を追加し、zip ファイルに含めるファイルやディレクトリを指定します。

files フィールドを指定した場合、含める必要のあるファイルやディレクトリを全て指定する必要があります(readme.txt と package.json は指定しなくても自動的に含まれます)。

以下では files フィールドに build と src ディレクトリ及び my-first-block.php(プラグインファイル)を指定しています。

{
  "name": "my-first-block",
  "version": "0.1.0",
  "description": "Example block scaffolded with Create Block tool.",
  "author": "The WordPress Contributors",
  "license": "GPL-2.0-or-later",
  "main": "build/index.js",
  "scripts": {
    "build": "wp-scripts build",
    "format": "wp-scripts format",
    "lint:css": "wp-scripts lint-style",
    "lint:js": "wp-scripts lint-js",
    "packages-update": "wp-scripts packages-update",
    "plugin-zip": "wp-scripts plugin-zip",
    "start": "wp-scripts start"
  },
  "files": [ "build", "src", "my-first-block.php" ],
  "devDependencies": {
    "@wordpress/scripts": "^30.7.0"
  }
}

上記のように package.json を変更して、npm run plugin-zip を実行すると、例えば以下のように src ディレクトリのファイルも zip ファイルに含まれます。

% npm run plugin-zip

> my-first-block@0.1.0 plugin-zip
> wp-scripts plugin-zip

Creating archive for `my-first-block` plugin... 🎁

Using the `files` field from `package.json` to detect files:

  Adding `build/index-rtl.css`.
  Adding `build/index.css`.
  Adding `build/style-index-rtl.css`.
  Adding `build/style-index.css`.
  Adding `src/edit.js`.
  Adding `build/index.js`.
  Adding `src/index.js`.
  Adding `src/save.js`.
  Adding `build/view.js`.
  Adding `src/view.js`.
  Adding `build/block.json`.
  Adding `src/block.json`.
  Adding `package.json`.
  Adding `build/index.asset.php`.
  Adding `my-first-block.php`.
  Adding `build/view.asset.php`.
  Adding `src/editor.scss`.
  Adding `src/style.scss`.
  Adding `readme.txt`.

Done. `my-first-block.zip` is ready! 🎉

namespace(名前空間)

Gutenberg ブロックでは、すべてのブロックに namespace(名前空間)が必要です。namespace はブロック名が同じ名前を使用する可能性のある他のブロックと競合しないようにするためのものです。

また、namespace は複数のブロックを1つの名前空間の下にグループ化する方法としても使われます。

例えば、WordPress 本体のすべてのブロックは、名前空間 core を使用します。WordPress の標準の段落ブロックの名前は core/paragraph で、見出しブロックの名前は core/heading です。

これまでの例では、create-block コマンドを実行する際に、namespace を指定していないので、デフォルトの create-block という namespace(名前空間)が適用されています。

namespace の値はプロパティ名や関数名、ブロックのクラス名に使われます。例えば、生成されたひな型のファイルで namespace の値が使われているファイルには以下のようなものがあります。

プラグインファイル

プラグインファイルでは、13行目の @package CreateBlock とブロックを登録する関数の名前 create_block_my_first_block_block_init で create-block という namespace が使われています。

<?php
/**
* Plugin Name:       My First Block
* Description:       Example block scaffolded with Create Block tool.
* Requires at least: 6.6
* Requires PHP:      7.2
* Version:           0.1.0
* Author:            The WordPress Contributors
* License:           GPL-2.0-or-later
* License URI:       https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain:       my-first-block
*
* @package CreateBlock
*/

if ( ! defined( 'ABSPATH' ) ) {
  exit; // Exit if accessed directly.
}

function create_block_my_first_block_block_init() {
  register_block_type( __DIR__ . '/build' );
}
add_action( 'init', 'create_block_my_first_block_block_init' );

block.json

block.json では name プロパティの値に "create-block/my-first-block" のように使われています。

{
  "$schema": "https://schemas.wp.org/trunk/block.json",
  "apiVersion": 3,
  "name": "create-block/my-first-block",
  "version": "0.1.0",
  "title": "My First Block",
  "category": "widgets",
  "icon": "smiley",
  "description": "Example block scaffolded with Create Block tool.",
  "example": {},
  "supports": {
    "html": false
  },
  "textdomain": "my-first-block",
  "editorScript": "file:./index.js",
  "editorStyle": "file:./index.css",
  "style": "file:./style-index.css",
  "viewScript": "file:./view.js"
}

editor.scss と style.scss

editor.scss と style.scss では、セレクタのクラス名に .wp-block-create-block-my-first-block のように使われています。

.wp-block-create-block-my-first-block {
  border: 1px dotted #f00;
}
.wp-block-create-block-my-first-block {
  background-color: #21759b;
  color: #fff;
  padding: 2px;
}

後から namespace の値を変更するには、上記のファイルの create-block(または create_block や createBlock)の部分を変更します。

但し、最初からひな型を生成する際に --namespace オプションを指定するか、対話モードで namespace を指定することができるので、その方が簡単です。

以下は create-block コマンドの --namespace オプションに my-blocks を指定して実行する例です。

[注意] 以下を実行すると、これまでの例と同じ名前(slug)を指定しているので、これまでのファイルは全て上書きされて初期化され、ブロックのプラグインを有効化する前の状態になります。

% npx @wordpress/create-block@latest my-first-block --namespace my-blocks

上記コマンドにより、namespace の部分は my-blocks が使われ以下のようになります。

プラグインファイル

<?php
/**
* Plugin Name:       My First Block
* Description:       Example block scaffolded with Create Block tool.
* Requires at least: 6.6
* Requires PHP:      7.2
* Version:           0.1.0
* Author:            The WordPress Contributors
* License:           GPL-2.0-or-later
* License URI:       https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain:       my-first-block
*
* @package MyBlocks
*/

if ( ! defined( 'ABSPATH' ) ) {
  exit; // Exit if accessed directly.
}

function my_blocks_my_first_block_block_init() {
  register_block_type( __DIR__ . '/build' );
}
add_action( 'init', 'my_blocks_my_first_block_block_init' );

block.json

{
  "$schema": "https://schemas.wp.org/trunk/block.json",
  "apiVersion": 3,
  "name": "my-blocks/my-first-block",
  "version": "0.1.0",
  "title": "My First Block",
  "category": "widgets",
  "icon": "smiley",
  "description": "Example block scaffolded with Create Block tool.",
  "example": {},
  "supports": {
    "html": false
  },
  "textdomain": "my-first-block",
  "editorScript": "file:./index.js",
  "editorStyle": "file:./index.css",
  "style": "file:./style-index.css",
  "viewScript": "file:./view.js"
}

editor.scss と style.scss

.wp-block-my-blocks-my-first-block {
  border: 1px dotted #f00;
}
.wp-block-my-blocks-my-first-block {
  background-color: #21759b;
  color: #fff;
  padding: 2px;
}

後から namespace を変更するのは面倒なので、最初から namespace を指定した方が無難です。

ダイナミックブロックを作成

ダイナミックブロック(動的ブロック)を作成するには、create-block コマンドに slug(この場合は my-dynamic-block)と --variant=dynamic オプションを指定して実行します。以下では --namespace オプションも同時に指定しています。

% npx @wordpress/create-block@latest my-dynamic-block --variant=dynamic --namespace wdl-block

または、対話モードで variant オプションで dynamic を選択します。

 % npx @wordpress/create-block@latest

Let's customize your WordPress plugin with blocks:
? The template variant to use for this block:
  static  // デフォルトは static なので dynamic を選択します
❯ dynamic
・・・以下省略・・・

上記を実行すると例えば以下のようなフォルダ構成が作成されます。スタティックブロックの場合と異なり、save.js ファイルはありませんが、render.php ファイルがあります。

以下はプラグインファイル my-dynamic-block.php です。

内容的にはスタティックブロックのプラグインファイルと同じです。

<?php
/**
* Plugin Name:       My Dynamic Block
* Description:       Example block scaffolded with Create Block tool.
* Version:           0.1.0
* Requires at least: 6.7
* Requires PHP:      7.4
* Author:            The WordPress Contributors
* License:           GPL-2.0-or-later
* License URI:       https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain:       my-dynamic-block
*
* @package WdlBlock
*/

if ( ! defined( 'ABSPATH' ) ) {
  exit; // Exit if accessed directly.
}

function wdl_block_my_dynamic_block_block_init() {
  register_block_type( __DIR__ . '/build/my-dynamic-block' ); // ブロックをサーバーに登録
}
add_action( 'init', 'wdl_block_my_dynamic_block_block_init' );

ダイナミックブロックの PHP のブロック登録では、register_block_type() 関数でレンダリングメソッドを定義する必要があり、次の 2 つの方法のいずれかで行うことができます。

  1. render_callback にブロックの表示内容を生成するコールバック関数を指定する
  2. block.json に render プロパティを追加し、ブロックの表示内容を出力する PHP ファイルを指定する

create-block コマンドに --variant=dynamic オプションを指定して実行した場合、2つ目の block.json に render プロパティを追加する方法が使用されています。

以下は生成された block.json です。18行目で render プロパティに render.php が指定されています。

これにより、WordPress に render.php というファイル名のファイルを使用して、ブロックのコンテンツをフロントエンドでレンダリングするように指示します。

{
  "$schema": "https://schemas.wp.org/trunk/block.json",
  "apiVersion": 3,
  "name": "wdl-block/my-dynamic-block",
  "version": "0.1.0",
  "title": "My Dynamic Block",
  "category": "widgets",
  "icon": "smiley",
  "description": "Example block scaffolded with Create Block tool.",
  "example": {},
  "supports": {
    "html": false
  },
  "textdomain": "my-dynamic-block",
  "editorScript": "file:./index.js",
  "editorStyle": "file:./index.css",
  "style": "file:./style-index.css",
  "render": "file:./render.php",
  "viewScript": "file:./view.js"
}

以下はレンダリングメソッド(フロントエンドの出力)が定義された render.php です。

ダイナミックブロックでは、フロントエンドのレンダリングにはこの PHP ファイルが使用されます。

ファイル名には任意の名前を付けることができますが、変更した場合は、block.json の render プロパティの値(ファイルへのパス)も変更する必要があります。

<?php
/**
* @see https://github.com/WordPress/gutenberg/blob/trunk/docs/reference-guides/block-api/block-metadata.md#render
*/
?>
<p <?php echo get_block_wrapper_attributes(); ?>>
  <?php esc_html_e( 'My Dynamic Block – hello from a dynamic block!', 'my-dynamic-block' ); ?>
</p>

レンダリングメソッドでは、以下のデータを自動的に受け取ります(上記では使用されていません)。

  • $attributes: ブロックの属性の配列
  • $content: データベース内に保存されたブロックのマークアップ(もしあれば)
  • $block: レンダリングされたブロックを表す WP_Block クラスのインスタンス

また、 ブロックのラッパー要素の属性を取得するには、get_block_wrapper_attributes() を使います。

get_block_wrapper_attributes() のパラメータに id、class、style キーを持つ連想配列を指定することで、ラッパー要素にそれらの属性を追加することができます。

以下はラッパー要素に style 属性と class 属性を追加する例です。

<p <?php echo get_block_wrapper_attributes(array( 'style' => 'color:yellow', 'class' => 'foo' )); ?>>
  <?php esc_html_e( 'My Dynamic Block – hello from a dynamic block!', 'my-dynamic-block' ); ?>
</p>

以下は index.js です。save.js がないので registerBlockType() の 第2引数の構成オブジェクトでは edit プロパティのみが設定されています。

import { registerBlockType } from '@wordpress/blocks';
import './style.scss';
import Edit from './edit';
import metadata from './block.json';

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

以下は edit.js です。内容的にはスタティックブロックの場合と同じです。

import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';
import './editor.scss';

export default function Edit() {
  return (
    <p { ...useBlockProps() }>
      { __( 'My Dynamic Block – hello from the editor!','my-dynamic-block' ) }
    </p>
  );
}

複数ブロックを1つのプラグインとして作成

複数のブロックを1つのプラグインとして提供する場合のひな型と開発環境を作成する方法です。

以下がおおまかな手順です。

  1. crete-block コマンドでプロジェクトのディレクトリ(プラグインの構造)を作成
  2. 生成された src ディレクトリ内のすべてのファイルを削除(src ディレクトリを空に)
  3. src ディレクトリで crete-block コマンドに --no-plugin を指定して必要な数のブロックを作成
  4. 必要に応じて、各ブロックの block.json で category や icon、description を更新。また、国際化対応する場合は textdomain の値をプロジェクトのテキストドメイン名に変更(統一)
  5. プラグインファイルで全てのブロックを登録
  6. ビルドを実行

プロジェクトのディレクトリを作成

ターミナルで wp-content/plugins ディレクトリに移動します。

plugins ディレクトリで以下のコマンドを実行し、まずプラグインの構造と開発環境を作成ます。

この例では slug に custom-blocks を、namespace に wdl-block を指定しています。

スラッグ(slug)や名前空間(namespace)は、作成するプロジェクトに合わせて適宜変更します。

% npx @wordpress/create-block@latest custom-blocks --namespace wdl-block

上記を実行すると、スラッグに custom-blocks を指定したので、custom-blocks というディレクトリに「Custom Blocks」という名前のプラグインが作成されます。

生成されたプラグインファイル custom-blocks.php を確認すると以下のようになっています(デフォルトのコメント部分は削除してあります)。

<?php
/**
* Plugin Name:       Custom Blocks
* Description:       Example block scaffolded with Create Block tool.
* Version:           0.1.0
* Requires at least: 6.7
* Requires PHP:      7.4
* Author:            The WordPress Contributors
* License:           GPL-2.0-or-later
* License URI:       https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain:       custom-blocks
*
* @package WdlBlock
*/

if ( ! defined( 'ABSPATH' ) ) {
  exit; // Exit if accessed directly.
}

function wdl_block_custom_blocks_block_init() {
  register_block_type( __DIR__ . '/build/custom-blocks' );
}
add_action( 'init', 'wdl_block_custom_blocks_block_init' );

以下は生成された block.json です。

国際化で使用するこのプラグインの textdomain プロパティの値には crete-block コマンドで指定したスラッグの値 custom-blocks が使用されています。

この後で作成する各ブロックの textdomain の値は指定するスラッグに応じてそれぞれ異なる値が設定されます(対話モードで textdomain を指定することも可能です)。

翻訳を作成(国際化対応)する場合、全てのブロックで同じ textdomain を使用するほうが便利なので、後で作成するブロックの textdomain もこの値(custom-blocks)を使用するように変更します。

{
  "$schema": "https://schemas.wp.org/trunk/block.json",
  "apiVersion": 3,
  "name": "wdl-block/custom-blocks",
  "version": "0.1.0",
  "title": "Custom Blocks",
  "category": "widgets",
  "icon": "smiley",
  "description": "Example block scaffolded with Create Block tool.",
  "example": {},
  "supports": {
    "html": false
  },
  "textdomain": "custom-blocks",
  "editorScript": "file:./index.js",
  "editorStyle": "file:./index.css",
  "style": "file:./style-index.css",
  "viewScript": "file:./view.js"
}

以下はこの時点での build と src ディレクトリのファイル構成です。

 📁 custom-blocks
├──📁 build
│   └──📁 custom-blocks
│       ├── block.json
│       ├── index-rtl.css
│       ├── index.asset.php
│       ├── index.css
│       ├── index.js
│       ├── style-index-rtl.css
│       ├── style-index.css
│       ├── view.asset.php
│       └── view.js
├──📁 node_modules
├── custom-blocks.php
├── package-lock.json
├── package.json
├── readme.txt
└──📁 src
    └──📁 custom-blocks
        ├── block.json
        ├── edit.js
        ├── editor.scss
        ├── index.js
        ├── save.js
        ├── style.scss
        └── view.js

create-block コマンドの実行により、src ディレクトリのファイルがプリビルドされて build ディレクトリに出力されています。

以降では、まず src ディレクトリの中身を空にします。そして空になった src ディレクトリの中に複数のブロックのディレクトリ(とファイル)を作成します。

その後、作成した全てのブロックをプラグインファイルで登録し、ビルドを実行すると、build ディレクトリにそれぞれのブロックのディレクトリとファイルが出力され、build ディレクトリが更新されます。

src ディレクトリを空に

src ディレクトリ内の custom-blocks ディレクトリを削除して src ディレクトリを空にします。

コマンドラインから削除するには、ターミナルで rm -r コマンドを実行してディレクトリごと削除します。

% rm -r custom-blocks/src/custom-blocks

examine files in directory custom-blocks/src/custom-blocks? y
remove custom-blocks/src/custom-blocks/block.json? y
remove custom-blocks/src/custom-blocks/edit.js? y
remove custom-blocks/src/custom-blocks/editor.scss? y
remove custom-blocks/src/custom-blocks/save.js? y
remove custom-blocks/src/custom-blocks/index.js? y
remove custom-blocks/src/custom-blocks/style.scss? y
remove custom-blocks/src/custom-blocks/view.js? y
remove custom-blocks/src/custom-blocks? y

または、コードエディターでディレクトリを選択して削除します。

src にブロックを作成(--no-plugin)

ターミナルで src ディレクトリに移動します。

% cd custom-blocks/src 

続いて、以下の2つのコマンドを実行して、src ディレクトリに2つのブロックを作成します。

[重要] この時、--no-plugin オプション(create-block v.4.0.0 で導入)を指定して、必要なすべてのプラグインファイルを生成するのではなく、ブロックファイルのみを作成します。

また、--namespace にはプロジェクト作成時と同じ値(この例の場合は wdl-block)を指定します。

% npx @wordpress/create-block@latest block-one --no-plugin --namespace wdl-block
% npx @wordpress/create-block@latest block-two --no-plugin --namespace wdl-block

以下のように src ディレクトリに block-one と block-two の2つブロックのディレクトリとそれぞれのブロックの開発に必要なファイルが作成されます。

必要に応じて、更にブロックを作成(追加)します。また、後からブロックを追加することもできます。

対話モードで作成(textdomain を指定)

% npx @wordpress/create-block@latest  --no-plugin

create-block 4.58.0 からは、--no-plugin を指定して対話モード(slug を省略)で実行すると、textdomain オプション(以下11行目)を指定できるようになっています。

対話モードで textdomain を設定した場合、edit.js の翻訳関数の第2パラメータのテキストドメインも指定した値が使用されます。

% npx @wordpress/create-block@latest  --no-plugin  // slug を省略して --no-plugin を指定

Let's add a new block to your existing WordPress plugin:
✔ The template variant to use for this block: static
✔ The block slug used for identification (also the output folder name): block-two //スラッグ
✔ The internal namespace for the block name (something unique for your products): wdl-block //名前空間
✔ The display title for your block: Block Two
✔ The short description for your block (optional): Example block: Blcok Two.
✔ The dashicon to make it easier to identify your block (optional): smiley
✔ The category name to help users browse and discover your block: widgets
✔ The text domain used to make strings translatable in the block (optional): custom-blocks //テキストドメイン

block.json を更新

src ディレクトリに作成された各ブロックの block.json でブロックの情報(category や icon、description)を必要に応じて変更します。

国際化対応する場合は、texdomain の値を最初に実行した create-block コマンドに指定したスラッグの値 custom-blocks に変更し、各ブロックのテキストドメインを統一します(対話モードで texdomain を指定した場合は不要)。

以下では description の値をデフォルトから変更し、また、textdomain の値を block-one や block-two から custom-blocks に変更しています。

{
  "$schema": "https://schemas.wp.org/trunk/block.json",
  "apiVersion": 3,
  "name": "wdl-block/block-one",
  "version": "0.1.0",
  "title": "Block One",
  "category": "widgets",
  "icon": "smiley",
  "description": "Example block: Blcok One.",
  "example": {},
  "supports": {
    "html": false
  },
  "textdomain": "custom-blocks",
  "editorScript": "file:./index.js",
  "editorStyle": "file:./index.css",
  "style": "file:./style-index.css",
  "viewScript": "file:./view.js"
}
{
  "$schema": "https://schemas.wp.org/trunk/block.json",
  "apiVersion": 3,
  "name": "wdl-block/block-two",
  "version": "0.1.0",
  "title": "Block Two",
  "category": "widgets",
  "icon": "smiley",
  "description": "Example block: Blcok Two.",
  "example": {},
  "supports": {
    "html": false
  },
  "textdomain": "custom-blocks",
  "editorScript": "file:./index.js",
  "editorStyle": "file:./index.css",
  "style": "file:./style-index.css",
  "viewScript": "file:./view.js"
}

textdomain の値を変更した場合は、翻訳関数のテキストドメインの指定を変更します。

この例の場合、それぞれの edit.js の翻訳関数 __() の第2パラメータの値(テキストドメイン)を custom-blocks に変更します。

※ 対話モードで texdomain を指定した場合は、翻訳関数のテキストドメインも設定されています。

export default function Edit() {
  return (
    <p { ...useBlockProps() }>
      { __( 'Block One – hello from the editor!', 'custom-blocks' ) }
    </p>
  );
}
export default function Edit() {
  return (
    <p { ...useBlockProps() }>
      { __( 'Block Two – hello from the editor!', 'custom-blocks' ) }
    </p>
  );
}

全てのブロックを登録

プラグインファイル custom-blocks.php を開きます。

現時点ではブロックの登録は以下のように1つの register_block_type() 関数に build ディレクトリの custom-blocks ディレクトリへのパスが指定され、build/custom-blocks ディレクトリの block.json を参照してブロックが登録されるようになっています。

function wdl_block_custom_blocks_block_init() {
  register_block_type( __DIR__ . '/build/custom-blocks' );
}
add_action( 'init', 'wdl_block_custom_blocks_block_init' );

ブロックを登録する関数を以下のように変更します。

この後でビルドを実行すると build ディレクトリに各ブロックのディレクトリが作成され、それぞれの block.json が配置されます。そのため、各ブロックを登録するには、register_block_type() に各ブロックの block.json の場所(ディレクトリのパス)を指定します。

function wdl_block_custom_blocks_block_init() {
  register_block_type( __DIR__ . '/build/block-one' );
  register_block_type( __DIR__ . '/build/block-two' );
}
add_action( 'init', 'wdl_block_custom_blocks_block_init' );

glob() 関数で柔軟に登録

ブロックを登録する関数を以下のように書き換えます。

PHP の glob() 関数を使用すると、パターンにマッチするファイルのパスを取得できます。

glob(__DIR__.'/build/*') は、build ディレクトリ内の全てのブロックのパスの配列になります。

foreach() を使って glob() で取得したパスの配列の各要素を register_block_type() に渡しています。

以下では、ブロックが多くなっても register_block_type() をブロックごとに記述する必要がなく、また、ブロックを追加や削除した場合も書き換える必要がなくなり、柔軟にブロックを登録できます。

function wdl_block_custom_blocks_block_init() {
  foreach (glob(__DIR__ . '/build/*') as $block) {
    register_block_type($block);
  }
}
add_action('init', 'wdl_block_custom_blocks_block_init');

ダイナミックブロックの場合も、block.json に render プロパティを追加する方法でブロックを登録していれば(render_callback を使っていなければ)、変更は必要ありません。

ビルドを実行

プロジェクトのディレクトリ(custom-blocks)に移動して、npm start コマンドを実行します。

% npm start

上記の npm start または npm run build コマンドを実行すると、それぞれのブロックが build ディレクトリ内の独自のサブディレクトリにビルドされます。

プラグインを有効化

管理画面のプラグインページでブロックのプラグインを有効化します。

投稿の編集画面で、ブロックの挿入アイコン + をクリックして、検索に「block」と入力すると、Block One と Block Two が表示されます。

インサーターのウィジェットカテゴリーにも表示されるので、こちらから挿入することもできます。

2つのブロックを挿入すると、以下のように表示されます。

これで、2つのブロックを提供するプラグインのひな型と環境の構築は完了です。

src ディレクトリのそれぞれのブロックのディレクトリのファイルを使って開発を進めます。

例えば、npm start を実行した状態(開発モード)で以下のファイルを変更して保存すると、

import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';
import './editor.scss';

export default function Edit() {
  return (
    <p { ...useBlockProps() }>
      { /* 以下のテキストを変更 */ }
      { __( 'This is Block One!', 'custom-blocks' ) }
    </p>
  );
}
.wp-block-wdl-block-block-one {
  background-color: #219b2b;  /* 背景色を変更 */
  color: #fff;
  padding: 2px;
}
import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';
import './editor.scss';

export default function Edit() {
  return (
    <p { ...useBlockProps() }>
      { /* 以下のテキストを変更 */ }
      { __( 'This is Block Two!', 'custom-blocks' ) }
    </p>
  );
}
.wp-block-wdl-block-block-two {
  background-color: #ee4d29;  /* 背景色を変更 */
  color: #fff;
  padding: 2px;
}

エディターで確認すると、それぞれのブロックのテキストと背景色が変更されます。

ブロックを追加

後からブロックを追加することもできます。

開発モードの場合は、control + c で終了します。

ターミナルで src ディレクトリに移動して、create-block コマンドに --no-plugin オプションを指定して src ディレクトリに追加のブロックを作成します。この例では --variant=dynamic を指定してダイナミックブロックを作成しています。

% cd src
% npx @wordpress/create-block@latest block-three --no-plugin --variant=dynamic --namespace wdl-block

src/block-three/ の block.json と edit.js の textdomain の値を custom-blocks に変更します。

または、ブロック作成時に create-block コマンドに --no-plugin オプションを指定して対話モードで実行して textdomain の値に custom-blocks を指定します。

ブロックの登録は glob() 関数を使って自動的に追加されたディレクトリのパスを取得して登録しているので変更は必要ありません。

ターミナルで プラグインのディレクトリ(custom-blocks)に移動して npm start(または npm run build)を実行すると、追加したブロック block-three がビルドされます。

% cd ..
% npm start

すでにプラグインは有効化されているので、追加したブロックを使用することができます。

国際化対応する場合は、block-one や block-two と同様、block.json の textdomain プロパティを custom-blocks に変更し、翻訳関数 __() の第2パラメータの値を custom-blocks に変更します。

{
  "$schema": "https://schemas.wp.org/trunk/block.json",
  "apiVersion": 3,
  "name": "wdl-block/block-three",
  "version": "0.1.0",
  "title": "Block Three",
  "category": "widgets",
  "icon": "smiley",
  "description": "Example block scaffolded with Create Block tool.",
  "example": {},
  "supports": {
    "html": false
  },
  "textdomain": "custom-blocks",
  "editorScript": "file:./index.js",
  "editorStyle": "file:./index.css",
  "style": "file:./style-index.css",
  "viewScript": "file:./view.js"
}
export default function Edit() {
  return (
    <p { ...useBlockProps() }>
      { __( 'Block Three – hello from the editor!', 'custom-blocks' ) }
    </p>
  );
}

追加で作成した block-three はダイナミックブロックのひな型なので render.php が生成されていて、フロントエンドのレンダリングに翻訳関数 esc_html_e() が使われているので、その第2パラメータの値も custom-blocks に変更します。

<p <?php echo get_block_wrapper_attributes(); ?>>
  <?php esc_html_e( 'Block Three – hello from a dynamic block!', 'custom-blocks' ); ?>
</p>

開発モードでない場合はビルド(npm start または npm run build)を実行します。

国際化対応

複数ブロックの翻訳ファイルを作成する例です。

但し、もっと良い方法があるかもしれません。

カスタムブロックの翻訳の作成の詳細は以下を御覧ください。

Create Block で作成したカスタムブロックの国際化対応(翻訳の作成)

以下は WordPress のコマンドラインツール WP-CLI がインストールされていることを前提にしています。

プロジェクトのディレクトリ(custom-blocks)に移動して、languages ディレクトリを作成します。

% mkdir languages

languages ディレクトリに POT ファイル(custom-blocks.pot)を作成します。

% wp i18n make-pot ./ languages/custom-blocks.pot --exclude=src

作成した POT ファイルをコピーして PO ファイル(custom-blocks-ja.po)を languages ディレクトリに作成します。

% cp languages/custom-blocks.pot languages/custom-blocks-ja.po

PO ファイルに日本語翻訳用の言語の設定 "Language: ja\n" を追加(9行目)します。

そして翻訳が必要な msgid に対して、msgstr に翻訳を作成します。

# Copyright (C) 2025 The WordPress Contributors
# This file is distributed under the GPL-2.0-or-later.
msgid ""
msgstr ""
"Project-Id-Version: Custom Blocks 0.1.0\n"
"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/custom-blocks\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: ja\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"POT-Creation-Date: 2025-01-09T06:52:55+00:00\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"X-Generator: WP-CLI 2.11.0\n"
"X-Domain: custom-blocks\n"

#. Plugin Name of the plugin
#: custom-blocks.php
msgid "Custom Blocks"
msgstr "カスタムブロック"

#. Description of the plugin
#: custom-blocks.php
msgid "Example block scaffolded with Create Block tool."
msgstr "複数ブロックのカスタムブロックプラグイン(サンプル)"

#. Author of the plugin
#: custom-blocks.php
msgid "The WordPress Contributors"
msgstr ""

#: build/block-three/render.php:7
msgid "Block Three – hello from a dynamic block!"
msgstr "ブロック・スリー ダイナミックブロックからのハロー!"

#: build/block-one/index.js:57
#: build/block-one/index.js:35
msgid "This is Block One!"
msgstr "これはブロック・ワンです!"

#: build/block-three/index.js:57
#: build/block-three/index.js:35
msgid "Block Three – hello from the editor!"
msgstr "ブロック・スリーのエディターからのハロー!"

#: build/block-two/index.js:57
#: build/block-two/index.js:35
msgid "This is Block Two!"
msgstr "これはブロック・ツーです!"

#: build/block-one/block.json
msgctxt "block title"
msgid "Block One"
msgstr "ブロック・ワン"

#: build/block-one/block.json
msgctxt "block description"
msgid "Example block: Blcok One."
msgstr "サンプルブロックのブロック・ワンです。"

#: build/block-three/block.json
msgctxt "block title"
msgid "Block Three"
msgstr "ブロック・スリー"

#: build/block-three/block.json
msgctxt "block description"
msgid "Example block scaffolded with Create Block tool."
msgstr "Create Block ツールで作成したサンプルブロック。"

#: build/block-two/block.json
msgctxt "block title"
msgid "Block Two"
msgstr "ブロック・ツー"

#: build/block-two/block.json
msgctxt "block description"
msgid "Example block: Blcok Two."
msgstr "サンプルブロックのブロック・ツーです。"

PO ファイルをもとに JavaScript ファイル用の翻訳ファイル(JED 1.x JSON)を作成します。

% wp i18n make-json languages/custom-blocks-ja.po --no-purge

custom-blocks-ja-{md5}.json という JSON ファイルがブロックごとに生成されます。この例の場合は3つのブロックがあるので3つの JSON ファイルが生成されます。

{md5} の部分は翻訳対象の JavaScript ファイルの相対パスの MD5 ハッシュ値です。例えば block-one の場合は md5( 'build/block-one/index.js' ) になります。

PO ファイルをもとに PHP ファイルの翻訳用の MO ファイルを作成します。

% wp i18n make-mo languages/custom-blocks-ja.po

PO ファイルをもとに翻訳用の .l10n.php(PHP)ファイルを作成します。

% wp i18n make-php languages/custom-blocks-ja.po

MO ファイルと .l10n.php(PHP)ファイルが追加され、languages ディレクトリは以下のような構成になっています。

PHP ファイルの翻訳を適用するため、プラグインファイル(custom-blocks.php)の init アクションで load_plugin_textdomain を使って MO(または .l10n.php)ファイルをロードします。

load_plugin_textdomain() の第1引数には textdomain の値を指定します。

function wdl_block_custom_blocks_block_init() {

  //  MO ファイルをロード(追加)
  load_plugin_textdomain( 'custom-blocks', false, basename( __DIR__ ) . '/languages' );

  foreach (glob(__DIR__ . '/build/*') as $block) {
    register_block_type($block);
  }

}
add_action( 'init', 'wdl_block_custom_blocks_block_init' );

JavaScript ファイルの翻訳を適用するため、プラグインファイルで wp_set_script_translations を使って JSON ファイルをロードします。

wp_set_script_translations() の第1引数には JavaScript のハンドル名を、第2引数には textdomain の値を指定します。

詳細:JSON ファイルをロード

function wdl_block_custom_blocks_block_init() {

  load_plugin_textdomain( 'custom-blocks', false, basename( __DIR__ ) . '/languages' );

  foreach (glob(__DIR__ . '/build/*') as $block) {
    register_block_type($block);
  }

  // 各ブロックのブロック名の配列
  $block_names = ['wdl-block/block-one','wdl-block/block-two','wdl-block/block-three'];

  foreach ($block_names as $block_name) {
    // 各ブロックの JavaScript(editorScript)のハンドル名を取得
    $script_handle = generate_block_asset_handle( $block_name, 'editorScript' );
    // JSON ファイルをロード(
    wp_set_script_translations($script_handle, 'custom-blocks', plugin_dir_path(__FILE__) . 'languages');
  }

}
add_action( 'init', 'wdl_block_custom_blocks_block_init' );

上記は以下のように foreach() を1つにまとめて書き換えることができます。これにより、ブロック名の配列を自動的に取得できるので、手動で記述する必要がなくなります。

以下では generate_block_asset_handle() の第1引数に指定する各ブロックのブロック名を、$namespace.'/'.basename($block) として glob(__DIR__.'/build/*') で取得したパス($block)から作成しています。

function wdl_block_custom_blocks_block_init() {
  // テキストドメイン
  $textdomain = 'custom-blocks';
  // 名前空間
  $namespace = 'wdl-block';

  load_plugin_textdomain($textdomain, false, basename(__DIR__) . '/languages');

  // build ディレクトリ内の各ブロックのパスの配列
  $blocks = glob(__DIR__ . '/build/*');

  foreach ($blocks as $block) {
    // ブロックを登録
    register_block_type($block);
    // 各ブロックの JavaScript(editorScript)のハンドル名を取得
    $script_handle = generate_block_asset_handle($namespace . '/' . basename($block), 'editorScript');
    // JSON ファイルをロード(
    wp_set_script_translations($script_handle, $textdomain, plugin_dir_path(__FILE__) . 'languages');
  }
}
add_action('init', 'wdl_block_custom_blocks_block_init');

投稿に挿入したブロックを確認すると、言語設定が日本語の場合、以下のように日本語で表示されます。

プラグインページのタイトルや説明文も日本語で表示されます。

この例の場合、block-one と block-two の save.js では翻訳関数を使って国際化対応していないのでフロントエンド側は英語のままです。block-three の render.php では翻訳関数が使われているのでフロントエンド側も翻訳されます。

もし、block-one と block-two のフロントエンド側も国際化対応したい場合は、例えば、block-one の場合、save.js を以下のように書き換えます。

import { __ } from '@wordpress/i18n';  // 追加
import { useBlockProps } from '@wordpress/block-editor';

export default function save() {
  return (
    <p { ...useBlockProps.save() }>
      { __( 'This is Block One!', 'custom-blocks' ) }
    </p>
  );
}

block-two も同様に書き換えます。

そして、ビルドを実行後、翻訳ファイルを最初から(POT ファイルから)作り直します。

リファレンス

Create Block ツール関連ドキュメント

「複数ブロックを1つのプラグインとして作成する方法」は以下を参考にさせていただきました。