目次
- ブロック作成の概説
- 開発環境の用意
- ブロック本体 index.js の調整
- InnerBlockのjsファイルを作成・登録
- InnerBlockの実装
- index.js の edit/save メソッド
- スタイルの調整
- 完成
1. ブロック作成の概説
ブロックの作成には、WordPress用のnpmパッケージである@wordpress/create-blockを利用します。
Create Block は公式でサポートされるブロック作成方法です。WordPress プラグインを使用してブロックを登録します。Create Block はモダンなビルド設定を提供します。構成は必要ありません。PHP、JS、CSS コード、その他、プロジェクトの開始に必要なすべてのファイルを生成します。
@wordpress/create-block – Japanese Team — WordPress.org
npx
コマンドを実行すると、プラグインのPHPファイル、ブロック用jsファイルの雛形、scssファイルなど、Gutenbergブロック用のファイルと、ビルド環境が一式用意されます。jsはECMAScript2015( ES6 / ESNext )で書いていきます。
1.1 必要知識とスキル
ECMAScript2015 と JSX で書いて Babel でビルドしますが、ビルド環境は公式スクリプトが自動で構築してくれます。npm run
ができれば大体、大丈夫でしょう。JavaScript と JSX は基本的な構文や仕組みが分かっていれば問題ないかと思います。npm も package.json が読めてnpmコマンドが使えれば十分でしょう。
他には、プラグインのPHPでブロック用js/CSSを読み込ませますので、WordPressにおけるスクリプトのエンキュー方法など、確認しておくといいかと思います。 wp_register_script() | WordPress Developer Resources
ローカルでのWordPress実行環境は今回 wp-env を利用しました。ローカル実行環境は各自でご用意下さい。
1.2 作例ブロック
このようなフレームワークに関する定義リストのブロックを作ってみたいと思います。イメージとしてはACFの繰り返しフィールドに近いものです。
左図がGutenbergエディタでの表示と入力のモックアップで、右が表示のモックです。


フレームワーク名をdt
要素、登場年、言語、説明をそれぞれ3つのdd
要素とします。このdt
×1・dd
×3を一組として、一つの定義リスト(dl
要素)内に複数のフレームワークの説明を入力し、表示します。
InnerBlockとGutenbergコンポーネントを組み合わせて作っていきます。
2. 開発環境の用意
適当なフォルダで、npx @wordpress/create-block
で対話モードとして実行し、スラッグと名前空間、ブロックのタイトルを指定しました。各項目で特に指定がない場合は、何も入力せずenter
でデフォルト値が使われます。「The short description for your block」やライセンス項目などは今回、特に指定していません。

下記のように、最低限スラッグだけ指定すればいいのですが、ブロックの識別子がcreate-block/
となってしまう上に、後から識別子を変更するのは結構手間がかかるため、最初に指定しました。
npx @wordpress/create-block framework-dl-block
セットアップが完了すると、このように表示されます。

npxを実行したフォルダ内に、framework-dl-block
というスラッグ名のフォルダが生成され、フォルダ内にはプラグインとして使えるようにファイル一式が入っています。
生成されるファイルは下記の通りです。
editorconfig や gitignore も揃っているので、このままgit init
/ git commit -am "initial commit"
してGitでのトラッキングを始められます。
.editorconfig
.gitignore
block.json
framework-dl-block.php
package-lock.json
package.json
readme.txt
build
| index.asset.php
| index.css
| index.js
| style-index.css
|
src
| edit.js
| editor.scss
| index.js
| save.js
| style.scss
|
node_modules
ビルドコマンドを叩くと、src 内の jsファイルが babel によってビルドされてbuid フォルダに書き出されます。build/index.js ファイルを framework-dl-block.php 内のwp_register_script()
関数がエンキューすることで、Gutenberg内でオリジナルのブロックが使えるようになります。
ビルドしてみる
@wordpress/eslint-pluginとしてeslintもインストールされていますので、必要なら.eslintrc
をプロジェクトルートに配置します。
一度ビルドしてみます。
npm run build

srcのjs、scssがビルドされてbuildフォルダに出力されます。
セットアップ完了後に表示される、最初のコマンドnpm start
を試します。
npm start
こちらはファイル監視をして、変更が保存されると自動でビルドします。eslintで文法チェックもされているので、jsの文法が間違っているとエラーメッセージが出力され、ビルドは行われません。

終了する時は、ctrl-c
です。
コーディングスタイルに準拠するよう自動整形も利用できます。
npm run format:js

3. ブロック本体 index.js の調整
index.jsではregisterBlockType
関数に、ブロックの識別子とオブジェクトが渡されています。オブジェクト内は、各種設定・editメソッド・saveメソッドなど、Gutenbergのブロックとして必要な機能や設定が記述されています。edit/saveでのHTML出力はJSXで書かれています。
参照: ブロックの登録 – WordPress.org / JSX の導入 – React
npx @wordpress/create-block
で生成されたindex.jsは、そのままだと今回は使いにくいので調整します。
コメントは全削除。プロパティやコンポーネントの説明と参照URLが書いてありますが、コードの流れが追いにくくなるため削除します。説明とURLは目を通しておいて下さい。
edit.js/save.js も削除して import 文も削除。分割するほどの行数ではなく、InnerBlock の js にも edit / save のメソッドを実装するため、ファイル構成が冗長になってしまいますので、今回は削除。
多言語対応の __
関数のインポートも削ってしまってもいいのですが、今回は残してます。
index.jsは一旦、このようになります。
import { registerBlockType } from '@wordpress/blocks';
import { __ } from '@wordpress/i18n';
import './style.scss';
registerBlockType( 'framework-dl/framework-dl-block', {
title: __( 'Framework description list', 'framework-dl-block' ),
description: __(
'Example block written with ESNext standard and JSX support – build step required.',
'framework-dl-block'
),
category: 'widgets',
icon: 'smiley',
supports: {
// Removes support for an HTML mode.
html: false,
},
edit: ( { className } ) => {
return (
<p className={ className }>
{ __(
'Framework description list',
'framework-dl-block'
) }
</p>
);
},
save: () => {
return null;
},
} );
この状態で、ビルドを通せば最低限のブロックとして動作します。

4. InnerBlockのjsを作成、登録
4.1 InnerBlock用 jsファイルの作成
InnerBlockとして、もう一つ、ブロックのjsファイルを作ります。
src/framework-dd-block.js
import { registerBlockType } from '@wordpress/blocks';
import { __ } from '@wordpress/i18n';
import './style.scss';
registerBlockType( 'framework-dl/description-block', {
title: __( 'Framework description ', 'framework-dl-block' ),
description: __( 'Framework descriptions block', 'framework-dl-block' ),
category: 'widgets',
parent: [ 'framework-dl/framework-dl-block' ],
supports: {
// Removes support for an HTML mode.
html: false,
},
edit: ( { className } ) => {
return (
<p className={ className }>
{ __(
'Framework description block, this is inner block!',
'framework-dl-block'
) }
</p>
);
},
save: () => {
return null;
},
} );
index.jsファイルをコピーして、framework-dd-block.js にリネームして中身を書き換えました。
変更点は主に二つ。ブロック名と parent プロパティです。
registerBlockType( 'framework-dl/description-block', {
index.jsで登録するdlブロックと被らないよう、第1引数であるブロックの一意識別子を変えておきます。index.jsにてInnerBlockとして許可するブロックを指定する際に、この識別子を利用します。ファイル名と識別子は一致していなくても構いません。
また、下記のように「親」ブロックを指定することで、ページ内に自由に挿入できなくなります。InnerBlockとしてのみ使用するので、今回は「親」ブロックを設定して、framework-dl-block 以外では description-block を使えなくします。
parent: [ 'framework-dl/framework-dl-block' ],
この時点での、srcフォルダ内のファイルは下記の通りです。
src
framework-dd-block.js
index.js
style.scss
4.2 InnerBlockを使えるようにする
先に作ったframework-dd-block.js
をInnerBlockとして使えるように、index.jsのedit/saveメソッドを書き換えます。
参照:ネストしたブロック: InnerBlocks の使用 – WordPress.org
src/index.js – import 文
import { registerBlockType } from '@wordpress/blocks';
import { InnerBlocks } from '@wordpress/block-editor';
import { __ } from '@wordpress/i18n';
import './style.scss';
import './framework-dd-block.js';
InnerBlocksと、先に作った インナーブロック用jsファイルをインポートします。framework-dd-block.jsのregisterBlockType()
が実行されればいいので、変数に代入しません。そもそもframework-dd-block.jsにはexport宣言がないので、何も代入できません。
src/index.js – editメソッド
edit: ( { className } ) => {
return (
<dl className={ className }>
<InnerBlocks
allowedBlocks={ [ 'framework-dl/description-block' ] }
/>
</dl>
);
},
<InnerBlocks>
タグのプロパティで、許可するブロックを指定します。allowedBlocks
には framework-dd-block.js で登録したブロックの識別子を入れます。一種類しか許可しない場合でも、配列でないと allowedBlocks
プロパティに渡せないので配列に入れて代入します。
saveメソッドも、InnerBlocks
の内容を保存するよう実装します。
src/index.js – saveメソッド
save: () => {
return <InnerBlocks.Content />;
},
この時点で、Gutenbergエディタでは「Framework description list」ブロック内に、 「Framework description block, this is inner block! 」というテキストのブロックを複数、挿入できるようになっているはずです。

Gutenbergのエディターモードを切り替えてコードエディターモードにすると、ブロックの開始と終了を表すHTMLコメントのみが保存されていると思います。

<!-- wp:framework-dl/framework-dl-block -->
<!-- wp:framework-dl/description-block /-->
<!-- wp:framework-dl/description-block /-->
<!-- wp:framework-dl/description-block /-->
<!-- /wp:framework-dl/framework-dl-block -->
5. InnerBlockの実装
5.1 edit メソッドにコンポーネントを登録
Gutenbergエディタでブロック内に表示するフォームは、Gutenbergのコンポーネントを使って実装していきます。入力フォームは下図のようにControlコンポーネントを利用します。
参照: Component Reference | Block Editor Handbook | WordPress Developer Resources

使うコンポーネントは、
framework-dd-block.jsにて@wordpress/components
モジュールから上記コンポーネントをインポートするよう宣言を追記しておきます。
framework-dd-block.js
import {
Flex,
TextControl,
__experimentalNumberControl as NumberControl,
SelectControl,
TextareaControl,
} from '@wordpress/components';
登場年を入力する NumberControl は WordPress5.5のGutenbergでは実験的な実装となっているため、__experimentalNumberControl
と長いエクスポート名になっています。NumberControl
変数として扱えるようにエイリアスを使ってインポートします。
Flex コンポーネントは、タグで囲うだけでフレックスボックスにしてくれます。エディターでのレイアウトを組むのに便利なので、合わせてインポートしています。(editor-style.cssでフレックスボックスを指定することもできます)
続いてframework-dd-block.jsのeditメソッドにJSXでコンポーネントを記述します。
edit: ( { attributes, setAttributes } ) => {
const { name, since, language, description } = attributes;
return (
<>
<TextControl
placeholder="Framework name"
value={ name }
onChange={ ( value ) => setAttributes( { name: value } ) }
/>
<Flex>
<NumberControl
label="登場年"
shiftStep={ 1 }
value={ since }
onChange={ ( value ) =>
setAttributes( { since: value } )
}
/>
<SelectControl
label="言語"
options={ [
{ label: 'PHP', value: 'PHP' },
{ label: 'JavaScript', value: 'JavaScript' },
{ label: 'Ruby', value: 'Ruby' },
{ label: 'Erlang', value: 'Erlang' },
] }
value={ language }
onChange={ ( value ) =>
setAttributes( { language: value } )
}
/>
</Flex>
<TextareaControl
placeholder="概要"
value={ description }
onChange={ ( value ) =>
setAttributes( { description: value } )
}
/>
</>
);
},
attributes
、setAttributes
はブロックへの入力内容を保持するために必要なオブジェクト、関数です。editメソッド内で利用するため、引数として渡しておきます。グローバル変数のような感じで、特に宣言なく利用できます。attributes
について詳しくは次節で説明します。
HTML要素に規定されている属性に対しても、placeholder="概要"
のようにプロパティを設定できます。
value
に代入した内容が、各input要素の内容としてGutenbergエディタで表示されます。
onChange
には変更を検知した際の動作を書きます。今回はvalue
をattributes
プロパティに代入しています。
余談:setAttributesの他にも、特に宣言なくregisterBlockType
関数で利用できる変数がいくつかありますが、公式ハンドブックにも解説がない場合があります。気づいたらイシューを立ててみたり、ドキュメントを書いてみるといいでしょう。
Project Overview | Block Editor Handbook | WordPress Developer Resources
gutenberg/docs at master · WordPress/gutenberg · GitHub
5.2 attributesを設定
ブロック内で入力した内容はattributes
プロパティを利用して保存、読み出しを行います。
edit と save – Japanese Team — WordPress.org
attributes
プロパティはすべての利用可能な属性と対応する値を表します。属性はブロックタイプ登録の際にattributes
プロパティで記述されます。属性ソースを指定する方法については属性のドキュメントを参照してください。
registerBlockType
関数の第2引数のオブジェクトにattributesプロパティを追記します。attributesのプロパティ(=属性)には、保持したい値についての設定を記述していきます。
Framework dl blockでは、下表のように4種類の属性を保持します。
入力内容 | 使用コンポーネント | 保存先 |
フレームワーク名 | TextControl | attributes.name |
登場年 | NumberControl | attributes.since |
言語 | SelectControl | attributes.language |
概要 | TextareaControl | attributes.description |
完成形ではHTMLから読み出してattributesにセットするため、年を表すsince属性もinteger
でなく、string
とします。
parent: [ 'framework-dl/framework-dl-block' ],
supports: {
// Removes support for an HTML mode.
html: false,
},
attributes: {
name: {
type: 'string',
},
since: {
type: 'string',
default: 2010,
},
language: {
type: 'string',
},
description: {
type: 'string',
},
},
edit: ( { attributes, setAttributes } ) => {
attributes
で属性を設定したので、onChange
でsetAttributes
を実行すると、入力内容がattributes
に反映されます。
onChangeイベント時に、value と attributes を console.log に出力するとこのようになります。sinceプロパティはデフォルト値の2010
が格納されています。
<TextControl
placeholder="Framework name"
value={ name }
onChange={ ( value ) => {
console.log( 'TextControl value: ' + value );
setAttributes( { name: value } );
console.log( attributes );
}
}
/>

5.3 HTMLでの保存をSaveメソッドに実装
saveメソッドがnull
を返しているので、HTMLで保存するように実装します。
下記のようにブロックで入力したとして、

現時点では入力内容はJSON形式で、ブロックの開始、終了を表すHTMLコメント内に保持されます。Gutenbergをコードエディターモードに切り替えれば実際の保存内容が確認できます。このままではHTMLが保存されないためプレビューや投稿ページには何も表示されませんので、save
メソッドでJSXを記述しHTMLでDBに保存するよう実装します。
逆にnull
のままにしておけば、HTML構造に依存しない形でブロックの内容をDBに保存できます。このようにJSONで保存した場合は、HTMLを出力するレンダー関数を別途PHPにて実装する必要があります。
<!-- wp:framework-dl/framework-dl-block -->
<!-- wp:framework-dl/description-block {"name":"framework","since":2016,"language":"JavaScript","description":"A framework description.\nSomthing framework distinction."} /-->
<!-- wp:framework-dl/description-block {"name":"framework 2","since":2009,"description":"A framework description.\nSomthing framework distinction."} /-->
<!-- /wp:framework-dl/framework-dl-block -->
今回は、HTMLで保存するため、save
メソッドは下記のようになります。
save: ( { attributes } ) => {
return (
<>
<dt>{ attributes.name }</dt>
<dd>
<span className="since">{ attributes.since }</span>年~
</dd>
<dd>
言語:<span className="language">{ attributes.language }</span>
</dd>
<dd className="description">{ attributes.description }</dd>
</>
);
},
dt
dd
要素として表示したいフレームワーク名や言語、説明は、attributes
に保持されているので、引数としてattributes
を渡します。edit
メソッドのように、複数の変数へ分割代入せずに、直接attributes.name
などで値を呼び出しています。
登場年と言語に関しては、attributes.since
/ attributes.language
をspan
タグで括っています。下書きや公開状態の投稿をGutenbergエディターを開いて編集する場合、GutenbergはDBを読み込んでattributes
に値をセットして表示する仕組みになっています。
そのために、保存したHTMLのどこからname
/ since
などの値を読み取るかの指定をattributes
プロパティに追記します。
attributes: {
name: {
type: 'string',
source: 'text',
selector: 'dt',
},
since: {
type: 'string',
default: '2010',
source: 'text',
selector: 'span.since',
},
language: {
type: 'string',
source: 'text',
selector: 'span.language',
},
description: {
type: 'string',
source: 'text',
selector: 'dd.description',
},
},
Selector
プロパティでHTMLを指定します、jQueryでDOMを取得する感じです。Source
プロパティでは取得したHTML全体を使うか、内部テキストを使うか、などを指定します。default
でデフォルト値を入れておくこともできます。
属性 – Japanese Team — WordPress.org
例えばdescription
属性は、description
クラスのdd
タグから内部テキストを取得する設定となっています。
ブロックが表示される時には、このsource
/ selector
の設定に基づいてDBのHTMLからパースした値をattributes
にセットし、edit
メソッドではコンポーネントのvalue
にattributes
内の値を代入します。このようにして、DBに保存している内容をGutenbergで表示しています。
実際にどういうタイミングで読取りや受け渡しが行われるかは、Reactコンポーネントのライフサイクルとかに基づいていると思いますが、詳しくは調べてません。 state とライフサイクル – React
InnerBlockのjsはこれで完成で、最終的なコードはこうなります。
src/framework-dd-block.js
import { registerBlockType } from '@wordpress/blocks';
import {
Flex,
TextControl,
__experimentalNumberControl as NumberControl,
SelectControl,
TextareaControl,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import './style.scss';
registerBlockType( 'framework-dl/description-block', {
title: __( 'Framework description ', 'framework-dl-block' ),
description: __( 'Framework descriptions block', 'framework-dl-block' ),
category: 'widgets',
parent: [ 'framework-dl/framework-dl-block' ],
supports: {
// Removes support for an HTML mode.
html: false,
},
attributes: {
name: {
type: 'string',
source: 'text',
selector: 'dt',
},
since: {
type: 'string',
default: 2010,
source: 'text',
selector: 'span.since',
},
language: {
type: 'string',
source: 'text',
selector: 'span.language',
default: '',
},
description: {
type: 'string',
source: 'text',
selector: 'dd.description',
},
},
edit: ( { attributes, setAttributes } ) => {
const { name, since, language, description } = attributes;
return (
<>
<TextControl
placeholder="Framework name"
value={ name }
onChange={ ( value ) => setAttributes( { name: value } ) }
/>
<Flex>
<NumberControl
label="登場年"
shiftStep={ 1 }
value={ since }
onChange={ ( value ) =>
setAttributes( { since: value } )
}
/>
<SelectControl
label="言語"
options={ [
{ label: 'PHP', value: 'PHP' },
{ label: 'JavaScript', value: 'JavaScript' },
{ label: 'Ruby', value: 'Ruby' },
{ label: 'Erlang', value: 'Erlang' },
] }
value={ language }
onChange={ ( value ) =>
setAttributes( { language: value } )
}
/>
</Flex>
<TextareaControl
placeholder="概要"
value={ description }
onChange={ ( value ) =>
setAttributes( { description: value } )
}
/>
</>
);
},
save: ( { attributes } ) => {
return (
<>
<dt>{ attributes.name }</dt>
<dd>
<span className="since">{ attributes.since }</span>年~
</dd>
<dd>
言語:
<span className="language">{ attributes.language }</span>
</dd>
<dd className="description">{ attributes.description }</dd>
</>
);
},
} );
6. index.js の edit/save メソッド
iconを変更して、edit/saveメソッドはdl
タグを返すよう実装します。
icon: 'feedback',
edit: () => {
return (
<InnerBlocks
allowedBlocks={ [ 'framework-dl/description-block' ] }
/>
);
},
save: () => {
return (
<dl>
<InnerBlocks.Content />
</dl>
);
},
Gutenbergでのスタイルを調整したいのでクラス名を付与したいのですが、save
メソッドで返された最上位のHTML(ここではdl要素)には、自動的にclassName
が付与されます。よって、特に指定はなし。edit
メソッドではルート要素(returnされる最上位の要素)が見た目と一致しない場合があるため、明示的にclassName
を指定する必要があるそうです。
実際にWordPressが投稿を表示する際にthe_content()
関数で出力するHTMLはこのようになります。
<dl class="wp-block-framework-dl-framework-dl-block">
<dt>framework</dt>
<dd><span class="since">2007</span>年~</dd>
<dd>言語:<span class="language">JavaScript</span></dd>
<dd class="description">A framework description. Something framework distinction.</dd>
</dl>
参照: Edit and Save | Block Editor Handbook | WordPress Developer Resources
デフォルトで付与されるclassName
は、registerBlockType
関数に渡された一意識別子から生成されるようです。
framework-dl/framework-dl-block → wp-block-framework-dl-framework-dl-block
7.スタイルの調整
ブロックに対しクラス名が付与されているので、スタイルを当てます。
scssファイルが既に用意されていて、background-color
と padding
が指定されているので、追記していきます。
src/style.scss
.wp-block-framework-dl-framework-dl-block {
background-color: none;
padding: 2px;
dt {
border-bottom: solid 1px black;
}
dd, dt {
margin-left: 0;
}
}
src/index.jsで
、このscssファイルがインポートされているので一緒にビルドされます。
import './style.scss';
また、ビルド済みのCSSファイルは build/style-index.css で、framework-dl-block.phpにてエンキューの登録がされています。
$style_css = 'build/style-index.css';
wp_register_style(
'framework-dl-framework-dl-block-block',
plugins_url( $style_css, __FILE__ ),
array(),
filemtime( "$dir/$style_css" )
);
完成
コードエディターモードにすると、下記のようなHTMLでDBに保存されていることが分かります。
<!-- wp:framework-dl/framework-dl-block -->
<dl class="wp-block-framework-dl-framework-dl-block"><!-- wp:framework-dl/description-block -->
<dt>CakePHP</dt>
<div class="flex"><dd><span class="since">2006</span>年~</dd><dd>言語:<span class="language">PHP</span></dd></div>
<dd class="description">Ruby on Railsの概念を多く取り込んだWEBアプリケーションフレームワーク。PHPでは老舗。ビューが柔軟に構築できる。</dd>
<!-- /wp:framework-dl/description-block -->
<!-- wp:framework-dl/description-block -->
<dt>Ruby on Rails</dt>
<div class="flex"><dd><span class="since">2005</span>年~</dd><dd>言語:<span class="language">Ruby</span></dd></div>
<dd class="description">WEBアプリケーションフレームワークとしては古くかつ有名。MVC、スキャフォルド、設定より規約などの特徴を持ち、DRYであることを基本理念としている。2020年現在も広く使われている。</dd>
<!-- /wp:framework-dl/description-block -->
<!-- wp:framework-dl/description-block -->
<dt>Vue.js</dt>
<div class="flex"><dd><span class="since">2014</span>年~</dd><dd>言語:<span class="language">JavaScript</span></dd></div>
<dd class="description">プロジェクトの一部分に使うことも、シングルページアプリケーションの構築もできる軽量シンプルなUIフレームワーク。開発者は元々GoogleでAngular.jsの開発に携わっていた。</dd>
<!-- /wp:framework-dl/description-block -->
<!-- wp:framework-dl/description-block -->
<dt>Laravel</dt>
<div class="flex"><dd><span class="since">2010</span>年~</dd><dd>言語:<span class="language">PHP</span></dd></div>
<dd class="description">後発ながら高いシェアを誇る。Webアプリケーションに必要な機能は全部入り。フロントはVue.js、バックエンドは依存性注入ができる。Artisanコマンドも種類が豊富。</dd>
<!-- /wp:framework-dl/description-block --></dl>
<!-- /wp:framework-dl/framework-dl-block -->
GitHubにコードをアップしています。
https://github.com/akiya64/framework-dl-block/releases/tag/v1.0.0