WordPress ブロックエディタのプラグイン/テーマ開発(のフロントエンド部分)には React をベースとした重厚長大な専用開発環境が用意されていますが、ちょっとしたカスタマイズなら別にフロントエンド用のトランスパイラを使わなくても書けます。
というか、@wordpress/scripts@wp-6.9 のビルド設定では内部でモジュールのインポートをグローバル変数 wp 等の参照に変換しており(@wordpress/dependency-extraction-webpack-plugin)、モジュールバンドラはあまり使われていません。外部依存関係のないカスタムブロックだとビルド時はminifier程度しか動きません。
React JSX形式のソースを素のJSに書き換える
為念ですが、この記事のやり方で素のJSに書き換えられるのは WordPress プラグイン/テーマだけです。
こんな感じの最小構成のエディタプラグインは、JSX記法だと次のコードになります。
import { PluginDocumentSettingPanel } from "@wordpress/editor";
import { TextControl } from "@wordpress/components";
import { registerPlugin } from "@wordpress/plugins";
registerPlugin("my-custom-post-panel", {
render: () => return (
<PluginDocumentSettingPanel
name="my-custom-post-panel"
title="カスタム設定"
className="my-custom-post-panel"
>
<TextControl
label="オレオレフィールド"
help="オレオレ設定を追加できます"
onChange={(value) => console.log(value)}
/>
</PluginDocumentSettingPanel>
);
});
JSXをcreateElement()呼び出しに置換する
急にリテラル文字列でもないHTMLタグが出てきて??となったかもしれませんが、React JSXのHTMLタグはcreateElement()メソッド呼び出しの糖衣構文でしかないです。
なので、まずJSXを剥ぐとこうなる。
import { PluginDocumentSettingPanel } from "@wordpress/editor";
import { TextControl } from "@wordpress/components";
import { registerPlugin } from "@wordpress/plugins";
import { createElement as _el } from "@wordpress/element";
registerPlugin("my-custom-post-panel", {
render: () => _el(PluginDocumentSettingPanel, {
name: "my-custom-post-panel",
title: "カスタム設定",
className: "my-custom-post-panel",
},
[
_el(TextControl, {
label: "オレオレフィールド",
help: "オレオレ設定を追加できます",
onChange: (value) => console.log(value),
}),
],
);
});
構造としてはそこまで変わらないですね。createElement()メソッドは第1引数が要素の型、第2引数がオブジェクト型で要素の属性(classはJSで予約語なので代わりにclassNameを使う)、第3引数が子要素やテキストノードを含む配列になっています。
ちなみにdivタグとか普通のHTMLタグも必要であれば入れられます。コンポーネント名の代わりに文字列としてタグ名を渡せばいいだけです。
import文をグローバル変数参照に書き換える
モダンブラウザはネイティブでimport文をサポートしていますがURL参照のみです。今のところ論理的なパッケージ名の解決はサポートしていません。
WordPress本体は各パッケージを単独でjsファイルとして置いているわけではなく、ブロックエディタのロード時にまとめてグローバル変数wpに読み込んでいます。これは実は普通にブラウザの開発者ツールで見られます。

実は WordPress 公式の JS ビルドツールも import 文を規則正しくグローバル変数参照に書き換えているだけなのでここは簡単です。
import { createElement as _el } from "@wordpress/element"
これは最終的にはこういう文と等価になります。
const _el = window.wp.element.createElement;
つまり最初のオレオレプラグインは最終的にこうなります。
"use strict";
((wp) => {
const _el = wp.element.createElement;
wp.plugins.registerPlugin("my-custom-post-panel", {
render: () => _el(
wp.editor.PluginDocumentSettingPanel,
{
name: "my-custom-post-panel",
title: "カスタム設定",
className: "my-custom-post-panel",
},
[
_el(wp.components.TextControl, {
label: "オレオレフィールド",
help: "オレオレ設定を追加できます",
onChange: (value) => console.log(value),
}),
],
)
});
})(window.wp);
ね、簡単でしょう? ややこしいのは個別のコンポーネントの扱いなんだけど。
ちなみにブロックエディタ用のコンポーネントのグラフィカルなリファレンスは下記にあります。
もちろん、社内向けなどで UI の統一感をそこまで気にしないなら、<input>タグ等を直接使って実装してしまう方法もあります。
ブロックエディタプラグインの読み込み
カスタムブロックはこの記事で書いたものとはまた扱いが別なのでややこしいんですが、上記のようなプラグインなら単に通常のWordPressサイト用JSと同じようにブロックエディタ画面にwp_enqueue_scriptしてやればいいだけです。
ブロックエディタには専用のアクションフック enqueue_block_editor_assets があるのでそこで登録します。
add_action('enqueue_block_editor_assets', function () {
wp_enqueue_script('my-editor-plugin', 'editor/my-editor-plugin.js');
});
window.wp参照に補完を効かせる
公式ガイドの手順に沿って import 文を使うスタイルでコードを書いた場合は Visual Studio Code 等では一応ちゃんと補完が効くのですが(依存関係はけっこう重いですが)、window.wp の型については定義されていません。この記事のやり方でそのまま書くと any 型扱いされるか TypeScript で書くと未定義変数扱いでエラーになります。
正直なところ個別のコンポーネントについては結局リファレンスを引くなりチャピるなりしないと分からないことが多く補完がそこまで役に立つわけでもないのですが(かなりの部分がcreateElement()かuseXXX()になるし……)、でも不便なので雑にブラウザのコンソールにJSを投げて型定義を抽出しました。こちら。
npx @wordpress/create-block NPMは死ぬ
おまけ。2026年2月現在、とても残念なことに WordPress の公式サポートツール1で公式サイトの手順通りにスケルトンを生成しようとすると依存性を解決できずに落ちます。
$ npx @wordpress/create-block@latest test-block
Installing npm dependencies. It might take a couple of minutes...
Warning: Failed to install dependencies:
---- 中略 ----
npm error code E404
npm error 404 Not Found - GET https://registry.npmjs.org/@wordpress%2fvips - Not found
npm error 404
npm error 404 The requested resource '@wordpress/vips@^1.0.0-prerelease' could not be found or you do not have permission to access it.
@wordpress/vips - Not found❣
どうやら WordPress ではカスタムブロックの開発は VIP にしか許されないようです。
@latest が prerelease 版を指しているのが問題と思われますので、バージョンを指定してやり直します。Wordpress 本体側のマイナーバージョンごとにタグが切られているので、ここでは最新の6.9を指定してみます。
$ npx @wordpress/create-block@wp-6.9 test-block
---- 中略 ----
Done: WordPress plugin Test Block bootstrapped in the /home/foo/test-block directory.
いけた。
ちなみに@wordpress/vipsに直接依存しているのは @wordpress/upload-media のようで、package.jsonでoverridesしてやれば通ります。
"overrides": {
"@wordpress/upload-media": "wp-6.9"
}
