Interactivity API について
Topics
Interactivity API は、標準 (standard) のディレクティブシステムで、宣言型コードに基づいて、ブロックのフロントエンドにインタラクティビティ (相互作用、対話性) を追加します。
ディレクティブは特別な属性で HTML を拡張し、Interactivity API に指示して、DOM 要素に指定された動作を追加、あるいは DOM 要素を変換します。Alpine.js を知っていれば似たようなアプローチですが、特に WordPress とシームレスに動作するように設計されています。
API のゴール
Interactivity API の主要な目的は、フロントエンドにおける Gutenberg ブロックのインタラクティビティを扱う、標準で、シンプルな方法の提供です。
標準 (standard) は、カウンターやポップアップのようなシンプルなものから、即時ページナビゲーション、即時検索、カートとチェックアウトのような複雑な機能まで、リッチでインタラクティブなユーザー体験を開発者がより簡単に作成できるようにします。
こうしたユーザー体験はすべて、技術的には現在でも Interactivity API なしで可能です。しかし、ユーザー体験が複雑になればなるほど、またブロック同士の相互作用が大きくなればなるほど、開発者がサイトを構築、維持することはより難しくなります。開発者が自身で解決しなければならない課題が大量にあります。API はこのようなインタラクションをサポートするための、すぐに使える手段を提供することを目的としています。
この課題を解決するため、Interactivity API の要件や目標は次のように定義されました。
- ブロックファースト、PHP ファースト: API は PHP や現在のブロックシステムとうまく動作する必要があり、そこには WordPress で広く拡張されているダイナミックブロックも含まれます。サーバーサイドレンダリングもサポートしなければなりません。サーバーでレンダーされた HTML と、クライアントでハイドレーションされた HTML は完全に同じでなければなりません。これは SEO にもユーザー体験にも重要です。
- 後方互換性: API は、例えばサーバーでレンダーされる HTML を修正する WordPress のフックと互換性がなければなりません。また、国際化やサイト上の既存の JS ライブラリ (jQueryなど) との互換性も必要です。
- オプション、かつ、段階的な適用: 前の点と関連して、API はオプションのままでなければなりません。段階的な適用が可能でなければならず、すなわち、この API を使用しないインタラクティブブロックとも共存する必要があります。
- 宣言型でリアクティブ: API は宣言的なコードを使用し、データの変更をリッスンし、そのデータに依存する DOM の部分のみを更新しなければなりません。
- パフォーマンス: 最高のユーザー体験を保証するために、ランタイムは高速かつ軽量でなければなりません。
- 拡張性:WordPress が拡張性に重点を置いているのと同じように、この新しいシステムは、ほとんどのユースケースをカバーする拡張性パターンを提供しなければなりません。
- アトミック(atomic、原子的)で組み合わせ可能: 柔軟でスケーラブルなソリューションを作成するには、組み合わせて複雑なシステムを構築できる、小さく、再利用可能な部品が必要です。
- 既存のブロック開発ツールとの互換性:API は、追加のツールや開発者の設定なしで、既存のブロック構築ツールと統合できなければなりません。
これらすべての要件とは別に、任意のソリューション上でのクライアントサイドナビゲーションとの統合が、簡単で、実行可能でなければなりません。クライアントサイドナビゲーションは、ページ全体をリロードすることなくサイトのページ間を移動するプロセスで、ウェブ開発者が欲する、最も印象的なユーザー体験の一つです。そのため、この機能はこの新しいシステムと互換性がなければなりません。
なぜディレクティブなのか ?
ディレクティブは、さまざまな可能性とアプローチに関する深い研究の結果です。私たちは、このデザインが最も効果的に要件をカバーすることを発見しました。
ブロックファースト、PHP フレンドリー
この API はブロック世界のために設計され、ウェブの標準に密接に寄り添った WordPress の歴史を念頭に置いています。
ディレクティブは HTML の属性のため、ダイナミックブロックや PHP に最適です。
ダイナミックブロックの例
<div
data-wp-interactive='wpmovies'
<?php echo wp_interactivity_data_wp_context( array( 'isOpen' => false ) ); ?>
data-wp-watch="callbacks.logIsOpen"
>
<button
data-wp-on--click="actions.toggle"
data-wp-bind--aria-expanded="context.isOpen"
aria-controls="p-1"
>
Toggle
</button>
<p id="p-1" data-wp-bind--hidden="!context.isOpen">
This element is now visible!
</p>
</div>
上で見るように、data-wp-on--click
や data-wp-bind--hidden
などのディレクティブは、カスタム HTML 属性として追加されます。WordPress はこの HTML をサーバー上で処理でき、ディレクティブのロジックを処理し、適切なマークアップを作成します。
後方互換性
Interactivity API はサーバーサイドレンダリングと完全に動作するため、以下を含む WordPress のすべての API を使用できます。
- WordPress のフィルターとアクション: WordPress フックを使い続けながら、HTML を変更し、あるいはディレクティブさえも変更できます。さらに、既存のフックも期待通りに動作します。
- コアの翻訳 API: 例えば
__()
や_e()
です。HTML のテキストを翻訳したり、ディレクティブのサーバサイドでこれらのAPIを使用できます。
オプション、かつ、段階的な適用
Interactivity API パイプラインは、WordPress の強固な基盤とパターンの上に構築することで、進歩的な拡張を促進します。
例えばディレクティブを持つブロックは、他のインタラクティブ、または非インタラクティブなブロックと共存できます。つまり、ページ上に jQuery のような他のフレームワークを使っているブロックがあっても、すべて期待通りに動作します。
他のライブラリとの互換性ルールの例外が、Interactivity API を使用したフルページのクライアントサイドナビゲーションです。詳細は後述の「クライアントサイドナビゲーション」を参照してください。
宣言型でリアクティブ
Interactivity API は、他の一般的な JS フレームワークと同様のアプローチをとっています。すなわち、ステート、アクション、コールバックを分離し、それらを宣言的に定義します。なぜ宣言型なのでしょうか ?
宣言型コードではプログラムが何をすべきかを記述しますが、一方、命令型コードではプログラムがどのように動くべきかを記述します。宣言型アプローチを使用すると、元となるデータの変更に応じて UI が自動的に更新されます。命令型アプローチでは、データが変更されるたびに手動で UI を更新しなければなりません。次のコード例を見比べてください。
命令形コード
<button id="toggle-button">Toggle Element</button>
<p>This element is now visible!</p>
<script>
const button = document.getElementById("toggle-button");
button.addEventListener("click", () => {
const element = document.getElementById("element");
if(element) {
element.remove();
} else {
const newElement = document.createElement("p");
newElement.textContent = "This element is visible";
document.body.appendChild(newElement);
}
});
</script>
宣言型コード
これは上と同じユースケースですが、新しいシステムを使用した宣言型コードの例です。JavaScript のロジックはブロックの view.js
ファイルで定義し、render.php
のマークアップにディレクティブを追加します。
// view.js file
import { store, getContext } from "@wordpress/interactivity";
store( 'wpmovies', {
actions: {
toggle: () => {
const context = getContext();
context.isOpen = !context.isOpen;
},
},
});
<!-- Render.php file -->
<div
data-wp-interactive='wpmovies'
<?php echo wp_interactivity_data_wp_context( array( 'isOpen' => true ) ); ?>
>
<button
data-wp-on--click="actions.toggle"
data-wp-bind--aria-expanded="context.isOpen"
aria-controls="p-1"
>
Toggle
</button>
<p id="p-1" data-wp-bind--hidden="!context.isOpen">
This element is now visible!
</p>
</div>
単純なユーザー体験を作成する場合には命令型コードを使う方が簡単かもしれませんが、アプリケーションが複雑になるにつれて、それはかなり難しくなります。Interactivity API は、単純なものから腹圧なものまで、すべてのユースケースをカバーしなければなりません。そのため Interactivity API にはディレクティブを使用した宣言型アプローチの方が適しています。
パフォーマンス
API は可能な限りパフォーマンスが高くなるように設計されています。
- ディレクティブに必要なランタイムコードはわずか10KB で、すべてのブロックに対して一度だけロードされます。
- スクリプトはページのレンダリングをブロックせずにロードされます。
拡張性
ディレクティブは HTML から直接追加、削除、修正できます。例えば、ユーザーは render_block
フィルタ を使用して HTML とその動作を変更できます。
アトミックで組み合わせ可能
それぞれのディレクティブは DOM の小さな部分を制御します。複数のディレクティブを組み合わせることで、リッチでインタラクティブなユーザー体験を作成できます。
既存のブロック開発ツールとの互換性
この API は wp-scripts
のような標準のブロック構築ツールで、そのまますぐに動作します。wp-scripts
が Interactivity API を使用して適切にスクリプトモジュールをビルドするための唯一の要件は、build
と start
スクリプトの両方での –experimental-modules フラグの使用です。
クライアントサイドナビゲーション
Interactivity API には、サイトにクライアントサイドナビゲーションを追加するプリミティブが組み込まれています。この機能は完全にオプションですが、WordPress のレンダリングシステムを除外せずに、こうしたユーザー体験を作成する可能性を開きます。
Interactivity API を使用したフルページのクライアントサイドナビゲーションはまだ作業中です (#60951 参照)。Interactivity API を使用してフルページのクライアントサイドナビゲーションを有効にするには、現段階ではまだ、すべてのインタラクティブブロックが Interactivity API の使用を必須とするだろうと予想されています。この場合のみ、Interactivity API は他のライブラリ (jQueryなど) との完全な互換性はありません。
また、View Transitions APIとの相性もよく、開発者は簡単にページ遷移をアニメーションできます。
なぜ標準 (standard) なのか ?
Interactivity API を使用したブロックと、jQuery のような他のアプローチを使用したインタラクティブブロックは共存でき、すべてが期待通りに動作します。しかし Interactivity APIには、インタラクティブブロックにとっていくつかの利点があります。
- ブロック同士が簡単に通信できる。標準では、このコミュニケーションはデフォルトで処理されます。フロントエンドのインタラクティビティに個々のブロックが異なるアプローチを使用すれば、ブロック間のコミュニケーションはより複雑になり、異なる開発者がブロックを作成する場合はほとんど不可能になります。
- 組み合わせ可能性と互換性: インタラクティブブロックを組み合わせ、定義された振る舞いを持つ構造内に入れ子にできます。同じ標準に従うことで、完全に相互互換性があります。インタラクティブ性に対して個々のブロックが異なるアプローチを取れば、おそらく互換性は壊れるでしょう。
- ブラウザに送信されるサイズは少なくなります。個々のプラグインの作者が異なる JS フレームワークを使用すると、より多くのコードがフロントエンドに読み込まれます。すべてのブロックが同じものを使えば、コードは再利用されます。
- ページ上のすべてのブロックがこの標準を使用する場合、クライアントサイドナビゲーションのようなサイト全体の機能を有効にできます。
さらに、標準がインタラクティブブロックの作成に必要なほとんどを処理するため、WordPress は開発者の複雑さを最大限に吸収できます。
標準により吸収される複雑さ
図: 標準がある場合とない場合の複数の要素を比較した2列の表。標準がない場合、ブロックの開発者はすべての面倒を見なければならないが、一方、標準がある場合、標準により完全に処理されるもの: ツール、ハイドレーション、WordPress との統合、インタラクティブ部分の SSR、ブロック間のコミュニケーション、フロントエンドのパフォーマンス。部分的に対応: セキュリティ、アクセシビリティ、ベストプラクティス。開発者の責任: ブロックのロジック。標準がない場合、すべてが開発者の責任となる。
この吸収により、インタラクティブブロックの作成に必要な知識は少なくなり、開発者が決断に悩む場面も少なくなります。
標準を採用することで、他のインタラクティブブロックからの学習が簡単になり、コラボレーションとコードの再利用が促進されます。結果、開発プロセスはよりスリムになり、経験の少ない開発者にも優しくなります。
最終更新日: