自分のプラグインを7.0で動かしたら、メタボックスに仕込んでいたJavaScriptが、急に効かなくなりました。
エラーも出ていません。ただ、いつも掴んでいたはずのエディタの要素が、document.querySelector で取れない。null が返ってくる。半年前に書いて、ずっと動いていたコードです。何も変えていないのに、動かなくなった。
原因を追いかけて、ブロックエディタが7.0でiframeの中に入ったことに行き当たりました。ここから芋づる式に、add_meta_box で作ってきたメタボックスそのものが、7.0の新しい編集体験と噛み合わなくなっていることも分かりました。この2つは、根が同じで、直し方も同じです。移行したときの手順を書きます。
(※ 7.0まわりは開発中に仕様の変動がありました。最終的な挙動は、必ず公式のフィールドガイドと自分の環境で確認してください)
なぜ、掴めなくなったのか
7.0の前まで、ブロックエディタは、管理画面と同じページの中で動いていました。だから、メタボックスに置いたJavaScriptから、エディタの要素を document.querySelector で掴んで、値を読んだり書いたりできた。同じ文書の中にあったからです。
7.0では、エディタがiframeの中に入ります。iframeは、外側のページとは別の文書です。外から document.querySelector でエディタ内の要素を探しても、見つかりません。別の文書だから、掴めない。段階導入で、7.1(2026年8月)で完全に強制されます。
// ❌ 7.0のiframe化で動かなくなる:外側のdocumentからエディタ内を探す
const title = document.querySelector('.editor-post-title__input');
title.value = '...'; // iframe内なので、外側のdocumentからは掴めない
エディタの中を触りたいなら、DOMを直接掴むのではなく、エディタが用意しているデータのAPI(@wordpress/data など)を経由します。DOMの位置に依存したコードは、iframe化のたびに壊れる。位置ではなくデータで扱う、が7.0以降の前提でした。
クラシックメタボックスの、もう一つの問題
JSが掴めない件を追ううちに、add_meta_box 自体にも、別の問題があると分かりました。
7.0の目玉は、複数人が同じ投稿を同時に編集する仕組みです。ここに制約があります。クラシックメタボックスがある投稿タイプは、その同時編集が無効になる。Classicブロック(core/freeform)がある投稿も同様です。
つまり、add_meta_box を使い続けると、その投稿タイプだけ、7.0の新しい編集体験から外れます。動かなくなるわけではありませんが、新機能に乗れない旧道に取り残される。しかもiframe化で、メタボックス内のJSも見直しが要る。旧来のやり方が、二重に効かなくなっていく感じでした。
移行:register_post_meta に寄せる
対処は、メタボックスでやっていたことを、登録済みメタ+REST公開に移すことです。iframeの件も、メタボックスの件も、これで一度に片づきます。
まず、自分のプラグインの add_meta_box を全部洗い出します。ここが移行の起点です。
grep -rn "add_meta_box" ./
見つかったメタを、register_post_meta で登録し直します。肝は show_in_rest => true です。これがあると、ブロックエディタ側(REST経由)からメタを読み書きできるようになります。
add_action('init', function () {
register_post_meta('post', 'myplugin_subtitle', [
'show_in_rest' => true, // これでエディタ(REST)から扱える
'single' => true,
'type' => 'string',
'auth_callback' => function () {
return current_user_can('edit_posts');
},
]);
});
auth_callback を省くと、権限チェックが緩くなります。誰がこのメタを書き換えられるかを、ここで明示しておきます。
入力UIは、エディタ側のパネルで出す
メタボックスのHTMLフォームの代わりは、エディタのサイドパネル(プラグインサイドバー/ドキュメント設定パネル)に置きます。ここはJavaScript側の実装になります。
// エディタのドキュメント設定パネルに、メタの入力欄を足す(概念コード)
import { registerPlugin } from '@wordpress/plugins';
import { PluginDocumentSettingPanel } from '@wordpress/editor';
import { useEntityProp } from '@wordpress/core-data';
import { TextControl } from '@wordpress/components';
const Panel = () => {
const [meta, setMeta] = useEntityProp('postType', 'post', 'meta');
return (
<PluginDocumentSettingPanel title="Myplugin">
<TextControl
label="サブタイトル"
value={ meta.myplugin_subtitle || '' }
onChange={ (v) => setMeta({ ...meta, myplugin_subtitle: v }) }
/>
</PluginDocumentSettingPanel>
);
};
registerPlugin('myplugin-panel', { render: Panel });
DOMを直接掴んでいたころと違い、useEntityProp でメタを読み書きします。iframeの内か外かを気にしなくて済むのが、この形の利点です。エディタが管理しているデータに、正規の経路で触るからです。冒頭で null が返ってきた原因は、そもそもDOMを掴みにいっていたことでした。
保存側は、そのままでいい部分もある
register_post_meta で show_in_rest を有効にしておくと、エディタからの保存はREST経由で処理されます。旧来の save_post で $_POST を拾って update_post_meta していた処理は、エディタ経由の保存では通らなくなることがあります。
ただ、クラシックエディタや外部からの保存経路も残すなら、save_post 側を併存させる判断はありえます。自分は、エディタ経由をRESTに寄せつつ、nonceと権限を見たうえで save_post も残す形にしました。ここは、プラグインがどの経路から保存されうるかで変わります。
確認する順番
移行したら、この順で確かめます。
まず、メタがRESTに出ているか。/wp-json/wp/v2/posts/{id} を見て、meta に自分のキーがあるか。無ければ show_in_rest が原因です。
次に、エディタのパネルで値が読み書きできるか。入力して、保存して、リロードして残るか。
最後に、旧メタボックスのJavaScriptが、iframe前提のDOM操作を残していないか。document.querySelector でエディタ内を掴んでいる箇所がないか、grepで洗います。冒頭の自分のミスが、まさにこれでした。
早見でまとめ
- 7.0でエディタがiframe化(7.1で完全強制)。外側のdocumentからエディタ内DOMは掴めない
- クラシックメタボックス(add_meta_box)がある投稿タイプは、同時編集が無効になる
- 対処は
register_post_meta+show_in_rest => true。iframe対応とメタボックス問題を一度に解決 - 入力UIはエディタのパネルへ。
useEntityPropでメタを読み書き(DOM直接操作をやめる) - 保存経路は要確認。エディタ経由はREST。save_postを残すかはプラグイン次第
- 確認は「RESTに出ているか → パネルで読み書き → 旧JSのDOM操作の残り」の順
7.0対応で、いちばん腰が重かったのが、この add_meta_box からの移行でした。長く使ってきた書き方なので。ただ、データをRESTに出す形に寄せておくと、iframe化にも同時編集にも乗れて、結果として身軽になりました。役に立ったらストックして、7.0/7.1対応のとき見返してください。
ふだんはraplsworks.comで、WordPressプラグイン開発やClaude Codeまわりのことを書いています。