インタラクティビティAPIはどのように機能するのか?

その主な構成要素は次の3つです:

  • PreactPreact Signals を組み合わせて、ハイドレーション、クライアントロジック、クライアントサイドナビゲーションを実現します。
  • クライアントとサーバーの両方で理解できるHTMLディレクティブ。
  • HTML_Tag_Processor によって処理されるサーバーサイドロジック。

なぜディレクティブシステムを構築するのにPreactを選ぶのか?Reactや他のJavaScriptフレームワークではなく?

Preactは、インタラクティビティAPIの焦点であるフロントエンドの文脈において、ReactやVue、Svelte、Solidなどの他のJavaScriptフレームワークに対していくつかの利点があります:

  • 小さい:8kB、hookssignals を含みます。
  • DOMの差分を自動的に提供します。
  • オプションフックを通じて非常に拡張可能です。彼らはその拡張性をフック(preact/hooks)、Reactとの互換性(preact/compat)、および彼らのシグナル(@preact/signals)に利用しています。基本的に、DOMの差分アルゴリズムを除いてすべてです。
  • コアチームは素晴らしく、非常に助けになります。彼らはまた、この「アイランドベース」のPreactの使用を強化することに興味を持っています。

インタラクティビティAPIが使用されているため、GutenbergはReactからPreactに移行するのか?

いいえ。現時点では、その移行を行う計画はありません。完全にインタラクティブなアプリケーションとしてのエディタの要件と利点はかなり異なります。Preactには、Reactエコシステムとの完全な互換性を可能にする@preact/compatパッケージがありますが、多くの大規模なWebアプリケーションがそれを使用しています。しかし、ブロックエディタでPreactを使用しても、インタラクティビティAPIのフロントエンドのような利点は得られません。

ディレクティブを使用する代わりに考慮されたアプローチは何ですか?

多くの代替アプローチが考慮されました。以下はそのいくつかの簡単な要約です:

Reactと他のJavaScriptフレームワーク

Gutenbergの開発者がReactに慣れているため、最初にReactが考慮されました。Svelte、Vue.js、Angularなどの他の人気のあるJSフレームワークも考慮されましたが、どれも(Reactを含む)PHPフレンドリーではなく、WordPressのフックや国際化と互換性がありませんでした。

Alpine.js

Alpine.jsは素晴らしいフレームワークで、インタラクティビティAPIの多くの機能に影響を与えました。しかし、Alpine.jsはそのディレクティブのサーバーサイドレンダリングをサポートしておらず、WordPressブロックに特化した同様のシステムを持つことには多くの利点があります。

Preactは、サイズが小さく、パフォーマンスが優れている(特にsignalsの追加により)、カスタムディレクティブがPreactの宣言的な構文とツール(フック、シグナル)で書かれていること、Alpine.jsよりも戦闘テスト済みでコミュニティが大きいことなど、数多くの理由からAlpine.jsの代わりに選ばれました。また、Reactとの互換性があり(エディタからクライアントサイドでレンダリングされたコンポーネントを共有するため)、インタラクティビティAPIに対して、UI状態の保持を含む最速のDOM差分アルゴリズムを自動的に提供します。

さらに、Preactがバックグラウンドで動作することで、インタラクティビティAPIは「最終レイヤー」を管理し、WordPressの要件により適応できるようになります。たとえば、セキュリティリスクを避け、厳格なセキュリティポリシーに準拠するために、ディレクティブ内でJavaScript式を使用することは許可されておらず、すべてのWordPressディレクティブは仕様に準拠したHTML属性です。

詳細については、「なぜAlpineではなくPreactなのか?」の会話を見てください。

プレーンJavaScript

以下の回答を参照してください。

テンプレートDSL

インタラクティブなテンプレートを書くためのDSLを作成する可能性も研究されました。そのテンプレートDSLで書かれたコードは、JavaScriptとPHPの両方にコンパイルされます。しかし、プロダクショングレードのテンプレートコンパイラを作成することは複雑で、大きなリスクを伴う投資になります。このアプローチは、ディレクティブがコンパイルターゲットとして機能することで、将来的にまだ考慮されています。

ブロック開発者として、なぜインタラクティビティAPIを使用すべきなのか?Reactではなく?

フロントエンドでReactを使用すると、PHPでのサーバーレンダリングとスムーズに動作しません。ブロックをレンダリングするためにReactを使用するすべてのアプローチは、クライアントサイドのJavaScriptを使用してコンテンツをロードする必要があります。ブロックをクライアントでのみレンダリングすると、通常、ユーザーがコンテンツのロードを待っている間、空のプレースホルダーやスピナーを見つめることになり、悪いユーザーエクスペリエンスが生じます。

PHP拡張機能(v8jsなど)でJSを使用することも可能ですが、残念ながらPHP拡張機能は後方互換性がなく、PHPフォールバックがある場合にのみ使用できます。

現在、PHPでブロックをサーバーレンダリングし、かつフロントエンドで同じブロックをReactでレンダリングすることが可能です。しかし、これは開発者エクスペリエンスが悪化する結果となり、ロジックをPHPとReactの部分で重複させる必要があります。それだけでなく、WordPressのフックによって引き起こされる微妙なバグにさらされることになります!

サーバーレンダリングされたHTMLを変更するフック(フィルター)を持つサードパーティプラグインをインストールしたと想像してみてください。このフィルターがブロックのHTMLに単一のCSSクラスを追加するとしましょう。そのCSSクラスはサーバーレンダリングされたマークアップに存在します。フロントエンドでは、ブロックがReactで再レンダリングされますが、今度はそのCSSクラスが含まれないコンテンツが表示されます。なぜなら、WordPressのフックをReactでレンダリングされたコンテンツに適用する方法がないからです!

一方、インタラクティビティAPIは、ディレクティブがサーバーレンダリングされたHTMLに動作を追加するため、WordPressのフックと完全に連携するように設計されています。これにより、i18nなどのWordPressバックエンドAPIと自動的に連携します。

要約すると、インタラクティビティAPIを使用することは、単にReactを使用することに比べて次のような利点があります:

  • Reactを使用する場合、インタラクティブなブロックは、PHPのサーバー上で生成されるのと同じマークアップをクライアントでも生成する必要があります。インタラクティビティAPIを使用すると、ディレクティブがサーバーレンダリングされたHTMLに追加されるため、そのような要件はありません。
  • インタラクティビティAPIはPHPフレンドリーです。WordPressのフックや国際化などの他のサーバー機能と自動的に連携します。たとえば、Reactでは、サーバーで適用されるフックがどれかを知ることができず、その変更はハイドレーション後に上書きされます。
  • 標準を使用することのすべての利点

インタラクティビティAPIを使用することの利点は、jQueryやバニラJavaScriptを使用することと比べて何ですか?

主な違いは、インタラクティビティAPIが宣言的かつ反応的であるため、複雑なインタラクティブ体験の作成と維持がはるかに容易になることです。さらに、ブロックと連携するように特別に設計されており、インターブロック通信、互換性、クライアントサイドナビゲーションなどのサイト全体の機能といった上記の利点を提供する標準を提供します。

最後に、jQueryと比較すると、インタラクティビティAPIのランタイムは約10kbで、はるかに軽量です。実際、WordPressエコシステム全体でjQueryのような重いフレームワークを削除するための取り組みが進行中であり、これがその点で役立ちます。

React、PHP、そしてこのインタラクティビティAPIを知っておく必要がありますか?

このAPIを使用してブロックにフロントエンドのインタラクティビティを追加したい場合、短い答えは「はい」です。ブロックがインタラクティブでない場合、ブロック作成のワークフローはまったく同じままです。

インタラクティビティAPIは、WordPressのフロントエンド部分にインタラクティブな動作を統合するための新しい標準的な方法を導入します。これは、ブロックのエディタ部分を処理するためにReactを使用する必要があることを意味します。

一方、インタラクティブなブロックを作成したい場合、インタラクティビティAPIを使用すると、ツール、WordPressとの統合、インターブロック通信、またはインタラクティブな部分のサーバーサイドレンダリングなどの複雑なトピックに対処する必要はありません。

インタラクティビティAPIはブロックを超えて使用できますか?

もちろん、はい、ブロックに限定されません。インタラクティビティAPIがインタラクティブなブロックを作成するための標準を提供することについて多くの言及がありますが、それは最も一般的なユースケースであるためです。より一般的に言えば、インタラクティビティAPIの標準は、WordPressの任意の部分のフロントエンドに「インタラクティブな動作」を追加するために使用できます。

ブロックの外でインタラクティビティAPIを使用する詳細については、wp_interactivity_process_directives関数を参照してください。

これにより、すべてのインタラクティブなブロックをこのAPIを使用するように移行する必要がありますか?

いいえ。インタラクティビティAPIの外にあるブロックは、それを使用するブロックと共存できます。しかし、上記のように、APIを使用するブロックにはいくつかの利点があることを考慮してください:

  • ブロック同士が簡単に通信できます。標準があるため、この通信はデフォルトで処理されます。異なるブロックがフロントエンドのインタラクティビティに異なるアプローチを使用すると、インターブロック通信がより複雑になり、異なる開発者がブロックを作成する場合にはほぼ不可能になります。
  • コンポーザビリティと互換性:インタラクティブなブロックを組み合わせ、定義された動作を持つ構造にネストし、同じ標準に従うことで、完全に相互運用可能です。各ブロックが異なるインタラクティビティのアプローチを使用している場合、互換性が失われる可能性があります。
  • ブラウザに送信されるKBが少なくなります。各プラグインの著者が異なるJSフレームワークを使用すると、フロントエンドでより多くのコードが読み込まれます。すべてのブロックが同じものを使用すれば、コードが再利用されます。
  • ページ上のすべてのブロックがこの標準を使用している場合、クライアントサイドナビゲーションのようなサイト全体の機能を有効にできます。

このAPIを使用することのパフォーマンスへの影響は何ですか?非常にシンプルなユースケースに対してインタラクティビティAPIを読み込む価値はありますか?

APIはパフォーマンスを考慮して設計されているため、問題はないはずです:

  • ディレクティブに必要なランタイムコードは約10KBで、すべてのブロックに対して一度だけ読み込む必要があります。
  • インタラクティビティAPIに属するすべてのスクリプトモジュール([view.jsファイルを含む)は、ページのレンダリングをブロックせずに読み込まれます。
  • 進行中の探求では、ブロックがビューポートに入ったときにスクリプトの読み込みを遅延させる可能性について検討しています。このようにして、初期の読み込みが最適化され、ユーザーエクスペリエンスに影響を与えません。

Core Translation APIと連携しますか?

インタラクティビティAPIはサーバーサイドレンダリングと完全に連携するため、()_e()を含むすべてのWordPress APIを使用できます。通常通りHTML内のテキストを翻訳するために使用でき、サーバーサイドでwp_interactivity_state()を使用する際にストア内でも使用できます。これは次のように見えるかもしれません:

  1. // render.php
  2. wp_interactivity_state( 'favoriteMovies', array(
  3. "1" => array(
  4. "id" => "123-abc",
  5. "movieName" => __("someMovieName", "textdomain")
  6. ),
  7. ) );

スクリプトモジュール(インタラクティビティAPIに必要)と互換性のある翻訳APIが現在開発中です。この作業の進捗を追うには、#60234を確認してください。

XSSが心配です。JavaScriptはディレクティブに注入できますか?

いいえ。インタラクティビティAPIは、ディレクティブに値として参照を渡すことのみを許可します。このようにして、eval()を使用して完全なJavaScript式を評価する必要がないため、XSS攻撃を行うことは不可能です。

カスタムセキュリティポリシーと連携しますか?

はい。インタラクティビティAPIはeval()Function()コンストラクタを使用しないため、unsafe-evalコンテンツセキュリティポリシーに違反しません。また、任意のカスタムコンテンツセキュリティポリシーと連携するように設計されています。

ディレクティブを使用してAJAX/REST-APIリクエストを行うことはできますか?

もちろん。ディレクティブによって呼び出されるアクションやコールバックは、JavaScript関数ができることは何でも行うことができ、APIリクエストを行うことも含まれます。