2026年7月9日
2026年7月9日
npm workspacesでWordPressのブロックプラグインと共通コードをモノレポ管理する手順
npm workspaces は、1つのリポジトリの中にある複数の npm パッケージを、ルートの package.json からまとめて管理する npm の機能です(npm 7 以降)。WordPress の開発では、次のような場面で役に立ちます。
- 複数のブロックプラグインで、同じ JavaScript の関数や部品を使い回したい
- 依存パッケージのインストールとロックファイルを1か所にまとめたい
- すべてのプラグインを1つのコマンドでビルドしたい
この記事では、共通コード用のパッケージ1つと、それを使うブロックプラグイン1つを作り、@wordpress/scripts でビルドして配布用の ZIP を作るところまでを説明します。コマンドは Node.js 22(npm 10)の Docker コンテナで実行して確かめています(2026年11月時点)。
作る構成
my-wp-monorepo/
├── package.json ← ルート(workspaces を定義)
├── package-lock.json ← ロックファイルはルートに1つ
├── node_modules/ ← 依存パッケージはここにまとめて入る
├── packages/
│ └── shared/ ← 共通コード(@myorg/shared)
│ ├── package.json
│ └── index.js
└── plugins/
└── my-block/ ← ブロックプラグイン(my-block)
├── package.json
├── my-block.php
└── src/
├── block.json
└── index.js
前提
- Node.js と npm が入っていること。
@wordpress/scriptsは版ごとに対応する Node.js が決まっています。2026年11月時点の 37.1.0 は、Node.js 22.22.2 以上(22 系)、24.15.0 以上(24 系)、26 以上が対象です。 - ビルドしたプラグインを試す WordPress 環境があること。この記事のブロックは
apiVersion3 で書くので、WordPress 6.3 以降が対象です。
node -v
npm -v
ステップ1:ルートを作り、workspaces を定義する
mkdir my-wp-monorepo && cd my-wp-monorepo
npm init -y
npm pkg set private=true --json
npm pkg set 'workspaces[0]=packages/*' 'workspaces[1]=plugins/*'
ルートの package.json は次のようになります(npm init が入れる項目の一部は省略)。
{
"name": "my-wp-monorepo",
"version": "1.0.0",
"private": true,
"workspaces": [
"packages/*",
"plugins/*"
]
}
"private": true にしておくと、ルートのパッケージを誤って npm に公開することを防げます。workspaces には、ワークスペースとして扱うフォルダーをパターンで書きます。テーマも同じリポジトリで管理するなら themes/* を加えます。
ステップ2:ワークスペースを作る
npm init に -w(--workspace)を付けると、そのフォルダーに package.json を作り、ワークスペースとして登録します。
# 共通コード。名前を @myorg/shared にする
npm init -y -w packages/shared --scope=@myorg
# ブロックプラグイン。名前はプラグインのフォルダー名と同じ my-block にする
npm init -y -w plugins/my-block
# 共通コードを ES モジュールとして書く
npm pkg set type=module -w packages/shared
# npm init が入れる test スクリプトは使わないので消す
npm pkg delete scripts.test -w packages/shared -w plugins/my-block
プラグインのパッケージ名に @myorg/ のようなスコープを付けないのには理由があります。後で使う wp-scripts plugin-zip は、パッケージ名から ZIP の名前とメインの PHP ファイル名(my-block.php)を決めます。スコープ付きの名前にすると、メインの PHP ファイルが ZIP に入りませんでした。プラグインはパッケージ名=フォルダー名=メインファイル名にそろえておくと扱いやすくなります。
共通コードを書きます。packages/shared/index.js:
export function formatPrice( value ) {
return value.toLocaleString( 'ja-JP' ) + '円';
}
ステップ3:プラグインから共通コードを参照する
ワークスペースの名前を指定して npm install すると、npm はレジストリではなくリポジトリ内のパッケージを使います。
# my-block の dependencies に @myorg/shared を加える
npm install @myorg/shared -w plugins/my-block
# ビルドツールを my-block の devDependencies に加える
npm install @wordpress/scripts --save-dev -w plugins/my-block
plugins/my-block/package.json の dependencies には "@myorg/shared": "^1.0.0" が入り、ルートの node_modules/@myorg/shared は packages/shared へのシンボリックリンクになります。共通コードを書き換えると、インストールし直さなくてもプラグイン側にすぐ反映されます。
@wordpress/scripts などの依存パッケージは、原則としてルートの node_modules にまとめて入ります。ワークスペースごとに別の版が必要な場合だけ、そのワークスペースの中に入ります。
プラグイン側にビルド用のスクリプトを登録します。
npm pkg set scripts.build="wp-scripts build" scripts.start="wp-scripts start" scripts.plugin-zip="wp-scripts plugin-zip" -w plugins/my-block
ステップ4:ブロックプラグインのファイルを用意する
plugins/my-block/src/block.json:
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "myorg/price",
"title": "Price",
"category": "widgets",
"editorScript": "file:./index.js"
}
plugins/my-block/src/index.js:
import { registerBlockType } from '@wordpress/blocks';
import { formatPrice } from '@myorg/shared';
import metadata from './block.json';
registerBlockType( metadata.name, {
edit: () => <p>{ formatPrice( 1980 ) }</p>,
save: () => <p>{ formatPrice( 1980 ) }</p>,
} );
@wordpress/blocks はインストールしていませんが、wp-scripts build が WordPress 本体の wp-blocks スクリプトを使うように変換するので、このままビルドできます。
plugins/my-block/my-block.php(プラグインのメインファイル):
<?php
/**
* Plugin Name: My Block
* Description: npm workspaces で管理しているブロックのサンプル。
* Version: 1.0.0
* Requires at least: 6.5
* Text Domain: my-block
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
add_action( 'init', function () {
register_block_type( __DIR__ . '/build' );
} );
ステップ5:ビルドする
# 1つのワークスペースだけビルドする(名前でもパスでも指定できる)
npm run build -w my-block
# すべてのワークスペースで build を実行する(build が無いものは飛ばす)
npm run build --workspaces --if-present
ビルドすると plugins/my-block/build/ に次のファイルができます。
| ファイル | 内容 |
|---|---|
index.js |
src/index.js と、使っている共通コード(formatPrice)をまとめたもの |
index.asset.php |
依存するスクリプト(wp-blocks など)とキャッシュ用の版を返す PHP |
block.json |
src/block.json のコピー。register_block_type() が読む |
開発中は npm run start -w my-block で、ファイルを保存するたびに再ビルドされます。
ルートの package.json にまとめ用のスクリプトを置いておくと、ルートで npm run build と打つだけで済みます。
npm pkg set scripts.build="npm run build --workspaces --if-present"
依存関係がつながっているかは npm ls で確認できます。
$ npm ls @myorg/shared
my-wp-monorepo@1.0.0 /work/my-wp-monorepo
+-- @myorg/shared@1.0.0 -> ./packages/shared
`-- my-block@1.0.0 -> ./plugins/my-block
`-- @myorg/shared@1.0.0 deduped -> ./packages/shared
ステップ6:配布用の ZIP を作る
npm run plugin-zip -w my-block
plugins/my-block/my-block.zip ができ、中身は my-block/my-block.php と my-block/build/ の3ファイルです。共通コードは build/index.js にまとめて入っているので、WordPress に入れるプラグインに node_modules やモノレポの他のフォルダーは要りません。
ZIP に入れるファイルを自分で決めたい場合は、プラグインの package.json に files を書きます(例: "files": ["build", "my-block.php", "readme.txt"])。
手元の WordPress で試すときは、plugins/my-block フォルダーを WordPress の wp-content/plugins/ に置くか、シンボリックリンクを張ってから、管理画面でプラグインを有効化します。
運用のポイント
- ロックファイルはルートに1つ。
package-lock.jsonはルートにだけ作られます。リポジトリにはこれをコミットし、CI ではルートでnpm ciを実行すると、すべてのワークスペースの依存パッケージが入ります。 - 依存パッケージの追加は
-wを付けてルートで行う。 どのワークスペースに何を入れたかがコマンドに残り、手順書や CI にもそのまま書けます。 - 共通コードの変更はすべてのプラグインに影響する。 共通パッケージを変えたら、
npm run build --workspaces --if-presentで全プラグインをビルドし直して確認します。 - ビルド結果をコミットするかを決めておく。
build/をリポジトリに含めない場合は、デプロイの手順でビルドしてから ZIP を作ります。
ブロック開発そのものの始め方は create-blockでブロックの雛形を作る も参考にしてください。
まとめ
- ルートの
package.jsonに"private": trueとworkspacesを書き、npm init -wでワークスペースを作る npm install @myorg/shared -w plugins/my-blockで、リポジトリ内の共通パッケージをシンボリックリンクとして参照できる@wordpress/scriptsのbuildで共通コードがプラグインのbuild/index.jsにまとめられる- 全体のビルドは
npm run build --workspaces --if-present、配布はnpm run plugin-zip -w my-block - プラグインのパッケージ名はスコープを付けず、フォルダー名とメインファイル名にそろえる