この記事は Snow Monkey アドベントカレンダー 2019 12日目の記事です。
先日、Snow Monkey Blocks で大幅なリファクタリングをおこないました。
やったことは主に2つあります。
- 全てのブロックで
register_block_type()
を使うように変更 - ビルドに
wp-scripts
を使うように変更
全てのブロックで register_block_type() を使うように変更
Snow Monkey Blocks は全部で30個以上のブロックを持っています。これまでそれらのブロックを定義した JavaScript ファイルは、1つのファイルに結合し、wp_enqueue_script()
でそのファイルを読み込むという流れで読み込みをおこなっていました。
特にその方法でも問題なく動作はするのですが、Gutenberg Freaks のオンラインミートアップで Gutenberg Handbook を読んだときに、カスタムブロックの登録には register_block_type()
を使いましょうと書いてあることに気づきました。
具体的には、各ブロックごとに「エディター用の script」「エディター用の style」「フロント&エディター用の script」「フロント&エディター用の style」の各ファイルを wp_register_script()
、wp_register_style()
で準備しておき、それらを register_block_type()
経由で読み込ませるという流れになります。
サンプルコードは以下。
add_action(
'init',
function() {
wp_register_script( 'ハンドル名', ... );
~省略〜
wp_register_style( 'ハンドル名', ... );
register_block_type(
'plugin/block',
[
'editor_script' => 'エディター用 script のハンドル名',
'editor_style' => 'エディター用 style のハンドル名',
'script' => 'フロント&エディター用 script のハンドル名',
'style' => 'フロント&エディター用 style のハンドル名',
]
);
}
);
ハンドブック的には一応これが正しいカスタムブロックの登録方法になるようです。
ちなみに、WordPress 公式ディレクトリにカスタムブロックを含むプラグインを掲載すると、そのプラグインのページに「このプラグインは○個のブロックを提供します。」という表示がでるようになっています。1ファイルに結合して読み込ませる方法だとここの表示がおかしなことになるので、register_block_type()
で登録するようにしたほうが良いのかなと思います。
また、今後、プラグインディレクトリと同じようにブロックディレクトリなるものも用意されるように話が進んでいるそうです。そうなったときはおそらく各ブロックごとにブロックディレクトリに登録するようになると思うので(完全に予想)、いまのうちから register_block_type()
を使う形にして慣れておいたほうが良いのではと思います。
ビルドに wp-scripts を使うように変更
これまで Snow Monkey Blocks では、JavaScript のビルドを Webpack + Babel でおこなっていました。これもちゃんと環境を整えれば普通にビルドできるのですが、Gutenberg ハンドブックには @wordpress/scripts というライブラリを使ってビルドする例が掲載されています。
@wordpress/scripts に含まれる wp-scripts
というコマンドで JavaScript のビルドすることができます。複雑な Webpack や Babel の設定ファイルを一切用意することなく、ただ @wordpress/scripts を npm install して wp-scripts
コマンドを叩くだけで良いのです!カスタムブロックを初めてつくろうとするときに一番の障壁になるのが JavaScript のビルド環境の構築だと思うので、wp-scripts
はその問題を一気に解決してくれます。
ということでサンプルは以下。npm scripts として利用します。
{
"scripts": {
"build:accordion": "wp-scripts build block/accordion/editor --output-path=dist/block/accordion"
}
}
上記は block/accordion/editor.js
をビルドして dist/block/accordion/editor.js
に書き出すというコマンドになります。
このとき、dist/block/accordion
には editor.asset.php
という、{ファイル名}.asset.php
な PHP ファイルも書き出されます。カスタムブロックのエディター用 script を読み込むときは、その script 内で使っているブロックエディター用の script(例えば Rich Text Component の script とか)より後に読み込む必要があるため、wp_register_script()
の引数で dependencies
を指定することで読み込む順序を制御しなければなりません。
例えばこんな感じ。
wp_register_script(
'ハンドル名',
'ファイルパス',
[ 'wp-element', 'wp-polyfill' ] // ここで依存関係を指定
);
で、この依存関係はそのカスタムブロックが何に依存するかによって変わってくるので、なかなか指定がめんどくさいわけです。それが {ファイル名}.asset.php
で解決できるのです。 {ファイル名}.asset.php
にはそのカスタムブロックが依存するライブラリのハンドル名が自動的に書き出されるので、このファイルを include()
するだけで依存関係が解決できます。
$asset = include( '/PATH/TO/{ファイル名}.asset.php' );
wp_register_script(
'ハンドル名',
'ファイルパス',
$asset['dependencies']
);
おまけ:JavaScript の lint も wp-scripts でできる
下記のコマンドで、指定したディレクトリ名の JavaScript ファイルが正しい構文で書かれているかをチェックしてくれます。
wp-scripts lint-js ディレクトリ名
これもビルドと同じで本来ならややこしい設定ファイルを用意しなければならないのですが、wp-scripts
ではそのような設定ファイルは不要です。すばらしい!
ちなみに、Snow Monkey Blocks では設定ファイル .eslintrc.js
を用意しています…。globals
に一個キーを足したかったのですが、うまい方法がわからず、wp-scripts
の中に含まれる .eslintrc.js
をコピーしてきて globals
を追記し、Snow Monkey Blocks のルートに配置しました(ルートに設定ファイルがあるとそれが優先的に利用されます)。
module.exports = {
root: true,
extends: [
'plugin:@wordpress/eslint-plugin/recommended',
// Temporary workaround to use linting rules for both e2e and unit tests with all files
// until override files globbing logic is fixed when using with --config.
// @see https://github.com/eslint/eslint/issues/11558
'plugin:@wordpress/eslint-plugin/test-e2e',
'plugin:@wordpress/eslint-plugin/test-unit',
],
globals: {
smb: true,
},
};
この場合、もし @wordpress/scripts のアップデートで extends
が更新されてしまったら、僕がコピーしたファイルにも手動で反映しなければいけないため、良い方法とはいえません。もし良い解決策をご存じの方がいらっしゃればぜひ教えてください!
Snow Monkey アドベントカレンダー 2019、まだまだ空きがありますのでぜひお気軽にご参加どうぞ!(すでに僕はネタ切れであります!