「ブロックにトグルを付けたいだけなのに、jQueryを読み込むのは重すぎる。でもReactやVueをフロントに持ち込むのも大げさ……」——ブロック開発でこう悩んだ経験はありませんか。
2024年4月のWordPress 6.5で正式導入されたInteractivity APIは、まさにこの悩みを解決するために設計された。そしてWordPress 7.0では、このAPIがさらに成熟し、いくつかの重要な変更が加わる。
この記事では、Interactivity APIとは何か・なぜ今これが重要なのか・基本的な使い方から、WordPress 7.0での最新の変更点まで、実際に手を動かす開発者向けに整理した。
この記事の結論
Interactivity APIはWordPressブロックにインタラクションを追加するための公式標準で、jQuery・React・Vueに頼らず、HTMLにdata-wp-*属性を書くだけで動的なUIを実装できる。約10KBの共有ランタイム、SSR標準対応、ブロック間の状態共有が特徴。WordPress 7.0では新しいwatch()関数の追加、state.navigationの非推奨化、effect→watchへのシグナル変更が入る。新規ブロック開発ではInteractivity APIが第一選択、既存ブロックは7.0リリース前に移行確認が必須。
検証環境:WordPress 6.9.4 / PHP 8.3.21 / Cocoon 2.9.1.1 / Xserver(xs435215)
情報ソース:WordPress Developer Docs / Make WordPress Core / Gutenberg GitHub / WordPress Developer Blog(2026年4月時点の情報)
WordPress 7.0 関連記事
この記事はWordPress 7.0で進化するInteractivity APIの全体像を解説しています。WordPress 7.0の他の新機能・技術変更については以下もご覧ください。
WordPress 7.0の新機能を完全ガイド
WordPress 7.0の技術的変更点を深掘り
WordPress 7.0 アップデート完全ガイド
WordPress管理画面が13年ぶりに刷新——DataViewsの全貌
Interactivity APIとは何か——「WordPress専用のAlpine.js」だと思えばいい
Interactivity APIは、WordPressブロックにインタラクションを追加するための公式標準。jQuery・React・Vue・Alpine.jsといった外部フレームワークに頼らず、HTMLにdata-wp-*属性を書くだけで動的な振る舞いを実装できる。内部的にはPreactと@preact/signalsをベースに構築され、約10KBの共有ランタイムがすべての対話型ブロック間で再利用される。
Interactivity APIはWordPress 6.5(2024年4月リリース)で導入され、WordPress 6.6・6.7・6.8・6.9を経て成熟してきた。公式ドキュメントによれば、Interactivity APIはブロックのフロントエンドに双方向性を加えるための「標準的な方法」を提供する。
これまで開発者は、ブロックにインタラクションを追加するたびに「jQueryを使うか、バニラJSで書くか、独自のReactを持ち込むか」を選ぶ必要があった。Interactivity APIはその選択を不要にする。
Interactivity APIの5つの特徴
- 宣言的な構文:HTMLに
data-wp-*属性を書くだけで動作を定義 - 軽量なランタイム:約10KBの共有ランタイムがすべての対話型ブロック間で再利用される
- SSR標準対応:PHP側で初期状態を出力し、クライアント側で「水和(ハイドレーション)」
- ブロック間の通信:複数のブロックが同じストアを共有して状態を同期できる
- プログレッシブ・エンハンスメント:JavaScriptが無効でも基本コンテンツは表示される
コアブロックの一部——「検索」「クエリー」「ナビゲーション」「ファイル」——はすでにInteractivity APIで実装されている。日常的に目にしているブロックのインスタント検索や、ページ遷移なしの絞り込みは、このAPIの仕事だ。
「宣言的」と「命令的」の違いを理解する
命令的(Imperative)は「何をどうやるか」を手順で書く方式、宣言的(Declarative)は「どうあるべきか」を状態で書く方式。Interactivity APIは後者を採用しており、DOMを直接操作する必要がなくなる。状態が変われば、UIが自動的に追従する——これがVueやReactの開発者が「リアクティブ」と呼んでいる仕組みだ。
この違いを理解すると、Interactivity APIの設計思想がぐっと腹落ちする。具体例で比較してみよう。
命令的スタイル(jQuery的なアプローチ)
|
1 2 3 4 5 6 7 8 9 10 11 |
// jQueryで書く場合 $('.toggle-button').on('click', function() { const panel = $(this).siblings('.panel'); if (panel.hasClass('is-open')) { panel.removeClass('is-open'); panel.attr('aria-expanded', 'false'); } else { panel.addClass('is-open'); panel.attr('aria-expanded', 'true'); } }); |
このコードは「クリックされたら、クラスを取得して、条件分岐して、DOMを更新する」という手順を一つずつ指示している。動作としては正しいものの、状態管理とDOM操作が混ざっており、コードが複雑になるほど見通しが悪くなる。
宣言的スタイル(Interactivity API的なアプローチ)
|
1 2 3 4 5 6 7 8 9 10 11 |
<!-- HTMLに状態を宣言するだけ --> <div data-wp-interactive="my-block" data-wp-context='{"isOpen": false}'> <button data-wp-on--click="actions.toggle" data-wp-bind--aria-expanded="context.isOpen"> 開く・閉じる </button> <div data-wp-bind--hidden="!context.isOpen"> パネルの中身 </div> </div> |
こちらは「ボタンがクリックされたらtoggleアクションを実行する」「aria-expandedはisOpenの値に連動する」「hiddenは!isOpenの値に連動する」と、「どう連動するか」だけを書いている。DOMを自分で書き換える処理は一切ない。
状態が変われば、UIが自動的に追従する。これがVueやReactの開発者が「リアクティブ」と呼んでいる仕組みだ。
CSSの基本的なトラブルシューティングについては「CSS画面縮小で右側に隙間が出る原因と対処法」も参考になる。CSSで済む範囲とInteractivity APIの出番を切り分ける判断材料になるはずだ。
Interactivity APIの構成要素——ディレクティブ・ストア・コンテキスト
Interactivity APIは3つの要素で構成される。ディレクティブ(data-wp-*属性)で振る舞いをHTMLに宣言し、ストアでグローバルな状態とアクションを管理し、コンテキストでブロックインスタンスごとのスコープ付き状態を扱う。stateはグローバル共有(カート合計や現在拡大中の画像IDなど)、contextはローカル独立(各画像の拡大状態や各アコーディオンの開閉など)が使い分けの基本。
① ディレクティブ(Directives)
ディレクティブはdata-wp-で始まるHTML属性で、DOMに特別な振る舞いを与える。よく使うものをまとめる。
| ディレクティブ | 役割 | 使用例 |
|---|---|---|
data-wp-interactive |
名前空間を指定してAPIを有効化 | data-wp-interactive="my-plugin" |
data-wp-context |
ブロックごとのローカル状態を定義 | data-wp-context='{"isOpen":false}' |
data-wp-on--[event] |
イベントリスナーを追加 | data-wp-on--click="actions.toggle" |
data-wp-bind--[attr] |
属性を状態に連動させる | data-wp-bind--hidden="!context.isOpen" |
data-wp-class--[class] |
CSSクラスを条件付きで付与 | data-wp-class--is-active="context.isActive" |
data-wp-text |
要素のテキストを状態と同期 | data-wp-text="context.count" |
data-wp-each |
配列から要素をレンダリング | data-wp-each="context.items" |
data-wp-watch |
状態変化に反応してコールバック実行 | data-wp-watch="callbacks.onChange" |
② ストア(Store)
ストアは、状態(state)とアクション(actions)、副作用(callbacks)を定義するJavaScriptのオブジェクトだ。名前空間で識別される。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
import { store, getContext } from '@wordpress/interactivity'; store('my-plugin', { state: { // グローバルな状態(すべてのインスタンスで共有) totalCount: 0, }, actions: { toggle() { const context = getContext(); context.isOpen = !context.isOpen; }, }, callbacks: { logChanges() { const context = getContext(); console.log('状態が変更されました:', context); }, }, }); |
③ コンテキスト(Context)
コンテキストは、ブロックのインスタンスごとに独立した状態を保持する仕組みだ。たとえば同じページに10枚の画像ブロック(ライトボックス有効)を置いても、それぞれが独立したlightboxEnabled状態を持てる。クリックした画像だけが拡大されるのはこの仕組みのおかげだ。
stateはすべてのブロックインスタンスで共有したいグローバルな状態(カート内の合計金額や現在拡大中の画像IDなど)、contextはブロックごとに独立させたいローカルな状態(各画像の拡大フラグや各アコーディオンの開閉状態など)——この使い分けがInteractivity API設計の要だ。
実例——コア画像ブロックのライトボックスを見てみる
Interactivity APIがどう動いているかを知る最も簡単な方法は、すでにコアに組み込まれている画像ブロックのライトボックス機能(Expand on click)を観察することだ。WordPress 6.5以降、このライトボックスはInteractivity APIで実装されており、DevToolsを開けばdata-wp-interactive="core/image"などの属性が実際に付与されているのを確認できる。
Step 1:画像ブロックでライトボックスを有効化
WordPress 7.0 + Twenty Twenty-Fiveの環境で、投稿エディタを開く。画像ブロックを挿入し、投稿HTMLに以下のようにlightbox属性を追加する。
|
1 2 3 4 5 |
<!-- wp:image {"lightbox":{"enabled":true}} --> <figure class="wp-block-image"> <img src="example.jpg" alt=""/> </figure> <!-- /wp:image --> |
サイト全体でライトボックスを有効化する場合は、theme.jsonに以下を追記すればよい。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
{ "version": 3, "settings": { "blocks": { "core/image": { "lightbox": { "enabled": true, "allowEditing": true } } } } } |
Step 2:フロントエンドで出力されるHTMLを確認
投稿を公開してフロントエンドを表示すると、画像ブロックは次のようなHTMLに変換されている。
|
1 2 3 4 5 6 7 8 9 10 11 |
<figure class="wp-block-image" data-wp-interactive="core/image" data-wp-context='{"imageId":123, "lightboxEnabled":false, "scrollDelta":0, ...}' data-wp-on--click="actions.showLightbox" data-wp-class--has-lightbox-open="state.lightboxEnabled"> <img src="example.jpg" alt="" data-wp-bind--hidden="state.lightboxEnabled" /> </figure> |
注目すべきは以下の点だ。
data-wp-interactive="core/image"で名前空間を宣言data-wp-contextでこの画像インスタンス固有の状態(imageId、lightboxEnabledなど)を保持data-wp-on--clickでクリック時にストアのshowLightboxアクションを実行data-wp-class--has-lightbox-openで状態に応じてクラスを付与
Step 3:ストアの実装を理解する
コア実装では@wordpress/interactivityのストアAPIで以下のようなアクションが定義されている(簡略化した擬似コード)。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
import { store, getContext } from '@wordpress/interactivity'; store('core/image', { state: { // すべての画像インスタンスで共有 currentImageId: null, }, actions: { showLightbox() { const context = getContext(); context.lightboxEnabled = true; state.currentImageId = context.imageId; }, hideLightbox() { const context = getContext(); context.lightboxEnabled = false; state.currentImageId = null; }, }, }); |
この実装には、これまで解説してきたInteractivity APIの要素がすべて詰まっている。
- SSR対応:初期HTMLに
data-wp-contextでimageIdなどの状態が埋め込まれ、JavaScript読み込み前から画像が表示される - スコープ分離:同じページに10枚の画像があっても、各
figure要素が独立したcontextを持つため、クリックした画像だけが拡大される - ブロック間連携:
state.currentImageIdというグローバルな状態で、「今どの画像が拡大中か」を全ブロックで共有している - 宣言的記述:開閉ロジックはストアに集約され、HTMLは「どう連動するか」だけを宣言している
💡 自分で確認してみよう
画像ブロックのライトボックスが有効な投稿で、画像を右クリック→「検証」でDevToolsを開いてみてほしい。<figure>要素にdata-wp-interactiveやdata-wp-contextが実際に付与されている。これがInteractivity APIが動作している証拠だ。
なお、この画像ブロックの実装自体はGutenbergリポジトリでpackages/block-library/src/image/以下に公開されている。view.jsでストアが定義され、edit.jsでエディタ側のUIが実装されている——コアブロックのソースは、自分でInteractivity APIを使ったブロックを書くときの最良のリファレンスだ。
自作のインタラクティブブロックをWordPress.orgで公開する手順は「WordPress.orgのプラグイン審査に通すための全手順」で解説している。
SSR対応が標準で付いてくることの意味
Interactivity APIはサーバーサイドレンダリングを第一級市民として扱う。初期HTMLにPHPで状態が埋め込まれるため、SEOに強く、JavaScriptが読み込まれる前からユーザーはコンテンツを見られる。技術用語では「ハイドレーション」ではなく「アクティベーション」と呼ばれ、PHPのSSRを維持したままリアクティブ性を後から注入する設計だ。
従来のReactアプリは「JavaScriptが読み込まれて実行されて初めて画面が描画される」という仕組みだった。その結果、検索エンジンがコンテンツを認識しづらい(SEOに不利)、JavaScript読み込みまでの間に画面が真っ白になる、ネットワークが遅い環境ではUXが悪化する——という問題が生じていた。
Interactivity APIは、WordPress伝統のPHPによるSSRを維持したまま、そこにリアクティブ性を「後から注入」する設計だ。技術用語では「ハイドレーション」ではなく「アクティベーション」と呼ばれる。
WordPressコアチームが公開しているwpmovies.devは、Interactivity APIの真価を体感できる公式デモだ。ページ遷移なしのSPA的なナビゲーション、インスタントフィルター、スムーズな画面遷移——すべてがSSRとInteractivity APIで実装されている。
キャッシュとSSRの関係については「WordPressでCSS更新が反映されない|キャッシュ5層の切り分け」も参照してほしい。SSRで出力された初期HTMLがキャッシュされる仕組みを理解しておくと、Interactivity APIの動作をより深く把握できる。
WordPress 7.0での変更点——ここがアップデートの核心
WordPress 7.0ではInteractivity APIに4つの重要な変更が入る。新しいwatch()関数(DOMに依存しない状態監視)、state.navigationの非推奨化、内部的なeffect→watchへのシグナル変更、そして6.8から継続するwithSyncEvent()の必須化。既存ブロックの開発者は、7.0リリース前にこれらの移行確認が必須だ。
① 新しいwatch()関数の追加
Make WordPress Coreブログ(2026年2月23日付け)によれば、@wordpress/interactivityパッケージに新しいwatch()関数が追加された。これはDOMとは独立して状態の変化を監視できる関数だ。
|
1 2 3 4 5 6 7 8 9 10 11 |
import { store, watch } from '@wordpress/interactivity'; const { state } = store('my-plugin', { state: { count: 0 }, }); // DOMに依存せず、状態の変化を監視できる watch(() => { console.log('count changed:', state.count); // 分析ログの送信、ストア間の状態同期、副作用の実行などに使える }); |
これまでdata-wp-watchディレクティブでDOM要素に紐づけた監視しかできなかったが、watch()関数によってストアレベルでの副作用が実装しやすくなる。
② state.navigationの非推奨化
WordPress 7.0でstate.navigationが非推奨となる。クライアントサイドナビゲーション(SPA的な画面遷移)を使っているプラグインは、新しいAPIへの移行が必要だ。
同時に、@wordpress/create-blockスキャフォールディングツールに新しい対話型バリアントが追加され、クエリパラメータを使ったページネーション・検索・フィルタリングアーカイブなど、実際のユースケースに対応したテンプレートが利用できるようになった。
③ 内部的なシグナルのimport変更
Gutenberg 22.6(WordPress 7.0に含まれる)では、内部的にeffectからwatchへのimport変更が行われた。既存のブロックが直接@preact/signalsからインポートしている場合、以下のような変更が必要だ。
|
1 2 3 4 5 |
// 変更前 - import { effect } from '@preact/signals'; // 変更後 + import { watch } from '@preact/signals'; |
VictorStack AIによるWordPress 7.0開発者向けレビュー(2026年3月5日付け)では、「この変更は単純な検索置換ではなく、回帰テストのトリガーとして扱うべき」と警告されている。ルーター更新やハイドレーションの動作に影響する可能性がある。
④ withSyncEventの重要性(6.8から継続)
WordPress 6.8から、event.preventDefault()やevent.stopPropagation()などの同期イベントプロパティを使うアクションはwithSyncEvent()でラップすることが必須になっている。
|
1 2 3 4 5 6 7 8 9 10 11 |
import { store, withSyncEvent } from '@wordpress/interactivity'; store('my-plugin', { actions: { // event.preventDefault()を使う場合は withSyncEvent() でラップ handleSubmit: withSyncEvent((event) => { event.preventDefault(); // フォーム送信処理 }), }, }); |
これはInteractivity APIが将来的にアクションを「デフォルトで非同期」にするための布石だ。ラップしていないとWordPress 6.8以降で非推奨警告が表示され、将来のバージョンで動作しなくなる。
WordPress 7.0の他の技術的変更点(Abilities API・AI Client・DataViews・iframe化)については「WordPress 7.0の技術的変更点を深掘り」で詳しく解説している。
WordPress 7.0リリース前に確認すべきこと:
- Interactivity APIを使ったブロックで
effectを直接インポートしていないか確認する state.navigationを使っているコードがあれば移行計画を立てるevent.preventDefault()などを使うアクションがwithSyncEvent()でラップされているか確認する- CI環境でWordPress 6.9と7.0ベータの両方でテストを実行する
CI/CDでの自動テストについては「WP-CLI実戦編|GitHub ActionsでのCI/CD連携」が参考になる。
Interactivity APIはいつ使うべきか——判断基準
フロントエンドに「状態を持つUI」を作るならInteractivity APIが第一選択。アコーディオン・タブ・モーダル・インスタント検索・カート・フォームバリデーションなど、開閉状態や入力値を管理するUIに最適。一方、CSSだけで完結するホバーアニメーションや静的装飾、非常に複雑なSPA全体の構築には向かない。
Interactivity APIが向いているケース
- アコーディオン・タブ・モーダル:開閉状態を持つUI
- インスタント検索・フィルター:ページリロードなしの検索結果更新
- カート・お気に入り:ブロック間で状態を共有する必要がある機能
- SPA的なナビゲーション:ページ遷移なしの画面切り替え
- フォームバリデーション:入力内容に応じた即時フィードバック
Interactivity APIを使わなくてよいケース
- 静的な装飾のみのブロック(CSSで完結する)
- ホバーアニメーションなど
:hoverで済む演出 - JavaScriptを使わない純粋な表示ブロック
- 非常に複雑なSPAアプリケーション全体(Next.jsなどのほうが適している)
jQueryは今後もしばらく動作するが、WordPressコア本体からは段階的に依存が減らされている。新規ブロック開発ではjQueryを使わず、Interactivity APIを選ぶのが将来的なメンテナンス性の観点で有利だ。
Rapls AI ChatbotプラグインでもInteractivity APIの採用を検討した経緯がある。プラグインの設計判断については「Rapls AI Chatbot開発者が解説|なぜ作ったか・RAGの設計判断」を参照してほしい。
まとめ——Interactivity APIはWordPressブロック開発の「新しい標準」
WordPress 6.5で導入されたInteractivity APIは、7.0で成熟期を迎える。Core含む主要ブロックがこのAPIで書かれるようになり、プラグイン・テーマ開発者にとっても「避けて通れない」標準APIになった。新規ブロックはnpx @wordpress/create-block --template @wordpress/create-block-interactive-templateで今すぐ始められる。既存ブロックはeffect→watch、withSyncEvent、state.navigationの3点を7.0リリース前に確認すべき。
| 技術選択 | Interactivity APIとの比較 |
|---|---|
| jQuery | 命令的で状態管理が煩雑。コア依存も段階的に減少中 |
| React(フロント持ち込み) | 重量級でSSRの恩恵を失う。WordPressの設計思想と噛み合わない |
| Alpine.js | 類似の宣言的アプローチだが、WordPress固有のSSR連携機能がない |
| Interactivity API | 軽量・宣言的・SSR標準対応・ブロック間通信可能。WordPress公式 |
もしあなたが新しいブロックを作るなら、npx @wordpress/create-block --template @wordpress/create-block-interactive-templateのひとコマンドで今すぐ始められる。
既存のブロックを持っているなら、WordPress 7.0のリリース前にeffect→watchの変更、withSyncEventの適用、state.navigationの移行を確認しておこう。
SVNでのプラグイン公開手順については「WordPressプラグインを公開して学んだSVNの使い方」も併せて参照してほしい。
参考リンク:










コメント