[Gutenberg]複数のブロックを開発できる環境の制作

@wordpress/create-blockで制作したGutenbergの開発環境は1つのカスタムブロックしか制作する事ができません。

ですが、多くの場合制作したいブロックは複数でしょう。

私も複数のブロックが制作したく、「create-block環境で複数のブロックを制作する方法」を調べてみたのですが、少なくとも日本語で検索した限り、2022/11現在は有効な記事が見つからなかったので自作しました。

この記事で紹介する方法はオリジナルですので、もっといい方法があるかもしれません。

もしかすると英語で検索すればもっとよい記事が見つかるかもしれませんが、誰かの参考になればと思います。

目次

@wordpress/create-blockでひな形を用意

まずは@wordpress/create-blockでひな形を用意します。

すでに存在し、そのプラグインの中で複数ブロックに対応させたい場合はこの作業は必要ありません。

今回は0から作る想定をし、まずは以下のコマンドでひな形を用意します。

プラグインの名前はmultiple-blocksにします。

npx @wordpress/create-block multiple-blocks

まとめるためのディレクトリの用意

複数のブロックをまとめるためのディレクトリを用意します。

今回用意するディレクトリは2つです。

  • blocks:この中にブロックを格納します。
  • dynamic_blocks:ダイナミックブロックを格納します。

とう事で上2つのディレクトリを制作します。

すると以下のようなディレクトリ構造になるかと思います。

wp-content
└── plugins
    └── multiple-blocks // 制作したプラグイン
        ├── blocks // 複数のブロックが入る(新)
        ├── build // コンパイル後のコードが入る(元)
        ├── dynamic_blocks // ダイナミックブロックが入る(新)
        ├── node_modules // パッケージ
        ├── src // 開発用のコードが入る(元)
        ├── .editorconfig
        ├── .gitignore
        ├── multiple-blocks.php // プラグインのエントリーポイント
        ├── package-lock.json
        ├── package.json
        └── readme.txt

サンプルを移動

これで元々存在していたbuildとsrcは必要なくなりましたが、後の動作確認のためにsrcファイルはblocksの中に移動させておきます。

これからblocksの中には複数のブロックが入りますので、さらにディレクトリを制作し、その中にsrcを移動させましょう。

今回はsample-blockとします。

wp-content
└── plugins
    └── multiple-blocks
        ├── blocks
        |    └─sample-block
        |       └src // こちらに移動させる
        ...

buildディレクトリは必要ありませんので消します。

今制作したsample-blockが1つのブロックとなります。

これからブロックを追加したい場合は、このsample-blockをコピー→リネームして増やしていきます。

コンパイルしてbuildに入るはずだったコードは、各ブロックのディレクトリ内にsrcと並列でbuildというディレクトリを制作し、そこに格納します。

wp-content
└── plugins
    └── multiple-blocks
        ├── blocks
        |    └─sample-block
        |       ├──build // srcをコンパイルしたコードが入る
        |       └─src
        ...

package.jsonを修正

ディレクトリを移動させましたのでこのままではコンパイルスクリプトがディレクトリの設定が異なると、エラーを出しますのでパスを修正します。

package.jsonを開きスクリプトを以下のように修正しましょう。

"scripts": {
	"start": "wp-scripts start blocks/sample-block/src/index.js --output-path=blocks/sample-block/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",
},

scriptsないのstartを変更しています。

制作したブロックのコンパイルはwp-scriptsを使用して行います。

wp-scriptsにstartオプションをつける事で開発用のコンパイルを行います。

第二オプションでどのファイルをコンパイルするのかを指定します。

第三オプションでコンパイルしたデータの出力先を指定します。

今回はsample-blockをコンパイルしたいのですが、ブロックのエントリーポイントはindex.jsとなりますのでパスをblocks/sample-block/src/index.jsとセットします。

出力先は同じblocks/sample-block/ないのbuildディレクトリです。

これでyarn startコマンドを実行する事でコンパイルされ、blocks/sample-block/build/にコードが出力されます。

multiple-blocks.phpを修正

制作したブロックはプラグインのエントリーポイントで読み込みます。

今回はプラグイン名をmultiple-blocksで制作したのでmultiple-blocks.phpになります。

コンパイルされたコードがblocks/sample-block/build/に出力されましたが、パスが変わっていますのでmultiple-blocks.phpの読み込むパスの設定を変更します。

function create_block_block_multiple_blocks_init() {
	register_block_type( __DIR__ . '/blocks/sample-block/build/' );
}
add_action( 'init', 'create_block_block_multiple_blocks_init' );

ブロックの追加はregister_block_type関数を使用する事で可能です。

もし複数のブロックを制作した場合はこちらに追記していく事で対応可能です。

function create_block_block_multiple_blocks_init() {
	register_block_type( __DIR__ . '/blocks/sample-block/build/' );
	register_block_type( __DIR__ . '/blocks/sample-block2/build/' );
	register_block_type( __DIR__ . '/blocks/sample-block3/build/' );
	register_block_type( __DIR__ . '/blocks/sample-block4/build/' );
}
add_action( 'init', 'create_block_block_multiple_blocks_init' );

これで複数ブロックを開発する環境の制作は完了です。

ですが、このままですと少し不便です。その不便を解決する方法を次の章で解説します。

必用なパッケージをインストール

実は@wordpress/create-blockだけでは複数のブロックを制作する環境を構築するには不十分です。

作る事は可能なのですが、不便になってしまうのでサポートしてくれるスクリプトを用意する必要がります。

サポートスクリプトには以下2つのパッケージが必要になりますのでインストールしましょう。

  • npm-run-all
  • glob
yarn add npm-run-all glob

サポートスクリプトの制作

より快適な開発環境にするためにサポート用のスクリプトを制作します。

そもそも何が不便になるかと言うと、以下の2つです。

  1. ブロックが増えるとその分スクリプトも増えるので実行が面倒
  2. block.jsonを変更してもなぜか更新されないので手動でコピーする必要がある

1について

package.jsonを修正した章でwp-scriptsにパスの設定をしていきました。

パスの設定は1つのファイルしか対象にする事がで来ませんので新しいブロックを追加する度にあの設定を記載する必要があります。

"scripts": {
	"start": "wp-scripts start blocks/sample-block/src/index.js --output-path=blocks/sample-block/build/",
	"start:otherblock1": "wp-scripts start blocks/other-block1/src/index.js --output-path=blocks/other-block1/build/",
	"start:otherblock2": "wp-scripts start blocks/other-block2/src/index.js --output-path=blocks/other-block2/build/",
	"start:otherblock3": "wp-scripts start blocks/other-block3/src/index.js --output-path=blocks/other-block3/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"
},

ここまでは1度しか設定ないので手動でもよいでしょう。

ですが、これを実行する場合、毎回以下のようにすべてのコマンドを打ち込む必要が出てきます。

yarn start
yarn start:otherblock1
yarn start:otherblock2
yarn start:otherblock3
...

立ち上げの度に毎回発生する作業ですのでこれは何とかしたいものです。

2について

block.json以外のファイルについてはwp-scripts startを実行すると変更を監視し、ファイルを保存すると自動でコンパイルし、buildディレクトリの中身を更新してくれます。

ですが、今の所block.jsonのみbuildディレクトリに自動反映されないので手動でコピーする必要があります。

それは面倒ですので何とかしたいものです。

1の解決策

1の課題を解決するためには1つのコマンドで全てのスクリプトを実装させるという方法があります。

複数のスクリプトをまとめて実装するにはnpm-run-allを使用します。

以下のスクリプトをpackage.jsonに追加しましょう。

"start": "run-p start:*",

こうすることで次からはyarn startコマンドを実行するだけでstart:とついているスクリプトを全て実行する事ができます。

ですが、全ての処理を実行するとかなり重くなってしまいますので、ブロックを1つしか修正しなかった場合などは個別にstart:***を実行するとよいでしょう。

2の解決策

2の課題を解決するにはファイルを自動でコピーしてくれるスクリプトを制作します。

scripts/file-copy/index.jsを制作し以下のコードを記載します。

const fs = require('fs');
const glob = require('glob');

let files = [];

const copyFile = (pathList = []) => {
    if(pathList.length === 0) return;

    pathList.map(path => {
        if(path.inputPath === undefined || path.outputPath === undefined) return;

        try {
            fs.unlinkSync(path.outputPath);
        } catch (error) {}

        fs.copyFile(path.inputPath, path.outputPath, (err) => {
            if (err) {
                // console.log(`${path.inputPath}はすでに存在します。`);
                throw err;
            } else {
                // console.log(`[copy]${path.inputPath} to ${path.outputPath}`);
            }
        });
    });

}

glob('multiple-blocks/blocks/**/src/block.json', (err, filePaths) => {
    filePaths.forEach(inputPath => {
        let outputPath = inputPath.replace('src', 'build');
        files.push({
            inputPath,
            outputPath
        });
    });
    copyFile(files);
});

その後package.jsonにこちらのファイルコピー処理を実行するスクリプトを記載しましょう。

"copy:blockJson": "node scripts/file-copy/index.js"

block.jsonに変更があればyarn copy:blockJsonを実行する事で全てのブロックのsrc/block.jsonをbuild/にコピーする事が可能です。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

プログラムちょと書ける。
いまはバリ島でスクール作っている。
プログラムちょっとできる。

目次