HTMX は WordPress にとって大きな問題になるかもしれない
公開: 2024-05-10ブラウザーで豊かなユーザー エクスペリエンスを構築することは困難な作業になる可能性があり、多くの場合、大量の JavaScript コードが必要になります。 アプリケーションのニーズと野心が増大するにつれて、JavaScript コードも複雑になります。 したがって、開発者が JavaScript アプリの考え方や作成方法を頻繁に改訂していることは驚くべきことではありません。
前回の JS フレームワークからの日数。
WordPress プラグイン開発者にとってはさらに悪いことです。 私たちがターゲットとする環境は、私たちが制御するサーバーでも、ページ全体を完全に制御できるサーバーでもありません。 WordPress プラグインで JavaScript フレームワークをうまく使用することは非常に可能ですが、意図したり期待したりしなかった規模と複雑さのプロジェクトが完成することも非常に簡単です。
しかし、このようにする必要がなかったらどうなるでしょうか? この記事では、最新の Web UI が JavaScript でどのように構築されているか、開発者が直面する困難、および HTMX が提供する代替手段について説明します。 特に、HTMX と WordPress が天の組み合わせである理由を見ていきます。
私たちがここにたどり着いた経緯
JavaScript が登場する以前、ブラウザは基本的に単なる美化されたドキュメント リーダーでした。 そのため、Web 上のほとんどのエクスペリエンスは「マルチページ アプリケーション」 (略して MPA) でした。 MPA は、アプリケーション内の各ページに 1 つずつ、複数の HTML ドキュメントで構成される Web アプリケーションです。 ユーザーがアプリケーションを使用すると、使用可能なアクションが異なるさまざまなドキュメントが表示されます。
MPA は非常に簡単に構築できます。 ナビゲーションは<a>
タグを使用して他のドキュメントにリンクし、ユーザー入力は<form>
要素で取得できます。 サーバーはリンクおよびフォームのリクエストに新しい HTML ドキュメントで応答し、画面に表示されているページを置き換えます。
MPA の例としては、WP Admin がよく知られていると思います。 各管理ページは、サーバー上で実行されている WordPress PHP コードによって生成される HTML を含むドキュメントです。 WordPress 設定ページなど、WP Admin のほとんどのページは、ユーザーが送信できるフォームで構成される傾向があります。
逆に、シングルページ アプリケーション (SPA) は、単一の HTML ページを使用するアプリケーションです。 ナビゲーションとユーザー入力は JavaScript コードによって処理され、ページ全体を入れ替えたり更新したりすることなく、ページの一部をその場で動的に変更します。 これにより、よりスムーズで応答性の高いユーザー エクスペリエンスが実現します。
最近では、多くの Web アプリケーションが Web インターフェイスに SPA を使用しています。 RebelCode では、2 つの主要な WordPress プラグイン、Spotlight と Aggregator の管理インターフェイス用の SPA を構築しました。 WordPress の比較的新しいサイト エディターも、ブロックベースのポスト エディターと同様に SPA です。
私たちが支払う代償
SPA は、JavaScript で記述され、ブラウザーで実行される独自のアプリケーションです。 彼ら自身の定義は、サーバー リソースに即時アクセスできないという最大の注意点でもあります。 これは、SPA とサーバーの間に通信チャネルを確立する必要があることを意味します。
例として、簡単な WordPress プラグインを作成してみましょう。 このプラグインが提供するのは、
書籍を管理するためのシンプルな CRUD ユーザー インターフェイス。 サーバー上のプラグインの内部 API は次のようになります。
<?php function get_books(?int $count = null, int $page = 1): Book[]; function get_book(int $id): Book; function insert_book(Book $book): Book; function update_book(Book $book): Book; function delete_book(int $id): void;
最新の SPA インターフェイスを作成するには、React のような JavaScript フレームワークを使用します。 WordPress でも使用されている最も人気のある JavaScript フレームワーク。 まずは管理ページを追加しましょう。
<?php add_action('admin_menu', function () { add_menu_page('Books', 'Books', 'manage_options', 'books', 'books_page'); }); function books_page() { echo '<div></div>'; }
このページでは、残りの UI がレンダリングされる React アプリケーションのルートとして機能する単一の空の<div>
要素をレンダリングします。
const rootEl = document.getElementById("books-app"); const root = ReactDOM.createRoot(rootEl); root.render(<BooksApp />); function BooksApp() { return ( <div> <h1>My Books</h1> ... </div> ); }
では、データベースに保存されている書籍をリストするにはどうすればよいでしょうか? これを行うコードはサーバー上にあるため、それを呼び出して結果を取得する方法が必要です。
これを行うには、サーバーから JSON API を公開します。 その後、React アプリは API の URL でリクエストを作成し、JSON 形式で書籍を受け取り、リストをレンダリングします。 この例では、WordPress REST API にエンドポイントを追加したと仮定します。
GET https://my-wp-site.com/wp-json/books { "books": [ { "id": 15, "title": "Mistborn", "author": "Brandon Sanderson", }, { "id": 44, "title": "The Hobbit", "author": "JRR Tolkien", }, ] }
次に、書籍を取得してリストとしてレンダリングする React コンポーネントを作成します。
function BookList() { const [books, setBooks] = useState([]); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); useEffect( function () { setIsLoading(true); fetch("https://my-wp-site.com/wp-json/books") .then((res) => res.json()) .then((data) => setBooks(data.books)) .else((error) => setError(error)) .finally(() => setIsLoading(false)); }, [setBooks, setIsLoading], ); if (isLoading) { return <div>Loading...</div>; } if (error) { return <div>Error: {error}</div>; } return ( <ul> <li> {books.map((book) => ( <a key={book.id} href={book.url}> {book.title} </a> ))} </li> </ul> ); }
しかし、この解決策は単純すぎるため、ユーザー エクスペリエンスが粗くなります。 コンポーネントのマウント解除後の状態変更、応答のキャッシュ、失敗したクエリの再試行、または古い状態による最新の状態の上書きの防止には対応しません。 実際、React エフェクトでfetch()
を使用する方法は一般的に推奨されません。
多くの点で、これは従来の MPA よりも悪い可能性があります。 したがって、これを正しく行うには、クライアントにさらにいくつかのことを実装する必要があります。 または、より現実的には、サードパーティのパッケージを使用します。
しかし、書籍のリストを表示するだけでも、これらすべてが不釣り合いな量の労力のように感じられ始めています。 スムーズなユーザー エクスペリエンスを作成するために、本当に JavaScript アプリと JSON API を作成する必要がありますか?
これを MPA と対比してみましょう。MPA では、依存関係を持たずに、わずか数行の PHP コードで書籍リストのレンダリングを実行できます。
<?php function render_books() { ?> <ul> <?php foreach (get_books() as $book): ?> <li> <a href="<?= $book->url ?>"> <?= $book->title ?> </a> </li> <?php endforeach; ?> </ul> <?php }
しかし、もちろん、これは公平な比較ではありません。 この書籍のリストは単なる静的な HTML です。 状態の変化やユーザー入力には反応しません。
サーバー上で HTML をレンダリングしながら SPA のようなエクスペリエンスを実現したい場合、コードはデータベースに即座にアクセスできるため、サーバーでレンダリングされた HTML がブラウザーに到達する方法を見つける必要があります。以前の本のリストを置き換えます。 しかし、JavaScript コードなしでこれを実現することは現時点では不可能なので、とにかく JavaScript を使用する必要があります。
しかし、自分で書く必要はありません。
HTMX の紹介
HTMX は、主に 1 つのことを行う小さな JavaScript ライブラリです。それは、HTML がサーバーから新しい HTML を要求できるようにすることです。 これは新しい属性を使用して行われます。これにより、新しい HTML をどこから取得するか、何と交換するか、何が交換のトリガーになるかを HTMX に伝えることができます。 これは、HTML サーバーとブラウザーのページの間のブリッジとして機能します。
現在のページを更新するクライアント JavaScript アプリケーションを構築しているわけではないため、これは SPA に関する考え方とは大きく異なります。 代わりに、いくつかの HTML 属性を追加して、特定のイベントが発生したときにページをどのように変更するかを HTMX に指示します。
HTML を使用しなくても、非常に限定的な方法ではありますが、HTML だけを使用して画面に表示される内容を変更することができます。 この HTML 機能、つまり謙虚な<a>
リンク要素についてはすでにご存知でしょう。
<a href="https://my-wp-site.com/books">View books</a>
link 要素は、ナビゲーションを実行するために必要なすべての情報をブラウザーに提供します。 これがクリックされると、ブラウザーは要素からhref
を取得し、その URL でリクエストを作成し、レスポンスをダウンロードし、それに HTML が含まれていると想定して、ページのコンテンツを新しい HTML に置き換えます。
<form>
要素は、HTML が新しい HTML をリクエストする方法のもう 1 つの例です。
<form action="/contact.php"> <label> Your message: <input type="text" name="message" /> </label> <button type="submit">Send message</button> </form>
今回は、ブラウザーがフォーム内のすべての入力から値を収集し、サーバーに送信し、応答をダウンロードして、画面に表示します。
HTMX の GitHub Readme より
<a>
と<form>
だけが HTTP リクエストを実行できるのはなぜですか? なぜ画面全体を交換するしかないのでしょうか?
さて、HTMX はそれを変えます。
<a href="https://my-wp-site.com/books" hx-target="#books"> View books </a> <div></div>
HTMX hx-target
属性を使用すると、リンクをクリックすると、 https://my-wp-site.com/books
からの応答が"books"
ID を持つ要素内に配置されます。 もちろん、ページを別のページ内に埋め込むことがここでの目標ではありません。 私たちのサーバーはページ全体で応答する必要はなく、代わりに HTML フラグメントで応答するだけで済みます。
サーバーから HTML フラグメントを公開し、それらのフラグメントをいつ、どこから、どのように取得するかを HTMX に指示することで、JavaScript を使用せずにサーバーが完全に制御する SPA のような Web アプリケーションを作成できます。 ある意味、HTML は新しい JSON になりました。
必要なのは、HTML スクリプトをページにロードすることだけです。
<script src="https://unpkg.com/[email protected]"></script>
(上記のコードは古い可能性があるため、手順については HTMX ドキュメントを必ず確認してください)。
別の例を見てみましょう。
<button hx-get="/button/off" hx-target="this" hx-swap="outerHTML"> Turn off </button>
ここではさらに多くのことが起こっているので、詳しく見てみましょう。
-
hx-get
、ボタンがクリックされたときにGET
リクエストを送信する URL を指定します。 -
hx-target="this"
クリックされたボタンと応答を交換するように HTMX に指示します。 -
hx-swap="outerHTML"
ボタンの中にあるものだけでなく、ボタン全体を交換するように HTMX に指示します。
まとめると、これは HTMX に次のように伝えます。
ボタンがクリックされると、GET リクエストを
/button/off
に送信し、このボタンをレスポンスに置き換えます。
サーバーが次の HTML で/button/off
に応答するとします。
<button hx-get="/button/on" hx-target="this" hx-swap="outerHTML"> Turn on </button>
違いが分かりますか? hx-get
属性は/button/on
を指すようになり、ボタン内のテキストは「オンにする」になりました。 このボタンをクリックすると、 /button/on
からの応答にも置き換えられます。 ご想像のとおり、サーバーに元のボタンで応答して切り替えを完了させることができます。
任意の要素がサーバーに新しい HTML を要求し、その HTML の送信先を決定できるようにするというこの単純なアイデアは、非常に強力であることがわかります。 タブの作成、ライブ結果による検索、プログレスバーなどを行うことができます。
長所と短所
ほとんどの JavaScript フレームワークとは異なり、HTMX ではクライアント アプリケーション コードをコンパイルしてバンドルする必要がありません。 これだけでも大きなメリットです。 JavaScript ビルド システムは、特に TypeScript、JSX、CSS プリプロセッサなどのより珍しい機能やライブラリを導入し始めると、セットアップと保守が非常に難しいことで知られています。中規模から大規模のチームでは、このタスクに専念する 1 人以上のメンバー。
もう 1 つの明白な利点は、個別のクライアント アプリケーションが不要なことです。 必要なのは HTML で応答する HTTP サーバーだけであるため、好きなプログラミング言語を使用できます。 チームが最新の JavaScript に精通していない場合、または 2 つのアプリケーションを構築するほど十分な規模ではない場合、これは大きなセールス ポイントになる可能性があります。 WordPress プラグイン開発者にとっては、プラグインのあらゆる側面に PHP を使用できるため、特に魅力的になる可能性があります。
しかし、おそらく最も重要な利点は、アプリケーションのバックエンドとフロントエンドの間に API が必要なくなることです。 これにより、開発時間を大幅に節約できるだけでなく、バグを引き起こす可能性のあるコードの量を減らすことができ、長期的にも時間を節約できます。
ただし、HTMX を使用するとJavaScriptを作成する必要がなくなると考えるほど単純に考える必要はありません。 ドラッグ アンド ドロップ、グラフ、色と日付のピッカーなどには、依然としてある程度の JavaScript が必要な場合があります。 ただし、SortableJS や Floating UI など、フレームワークに依存しないソリューションはいつでも使用できます。 さらに、Web 標準が最近の<dialog>
要素のような新しい HTML 要素で進化し続けるため、将来的には JavaScript の必要性が少なくなる可能性もあります。
次に、PHP は皮肉なことに、HTML テンプレートを作成するために構築されているにもかかわらず、HTML テンプレートがあまり得意ではありません。 そのタグ構文は過度に冗長であり、その HEREDOC 文字列構文では文字列補間のサポートが制限されています。
最後に、WordPress でエンドポイントを作成するのはそれほど簡単ではありません。 前の例の書籍プラグインを考えてみましょう。 HTML 形式で書籍のリストを返すサーバー上のパスが必要です。 このエンドポイントを登録するにはどうすればよいでしょうか?
-
init
またはadmin_init
アクション中に GET パラメータを検出しますか? - Admin Ajax API を使用しますか?
- REST API エンドポイントを登録しますか?
- カスタム書き換えルールを追加しますか?
多くのオプションがありますが、これほどシンプルなものはありません。
ハテオアス
前の例には非常に見落とされやすい微妙な詳細があり、一度指摘されると明白に聞こえるでしょう。
サーバーから HTML を取得すると、ページ上のボタンは ON バリアントまたは OFF バリアントのいずれかになります。 画面にどちらが表示されているかに応じて、クリック動作が異なります。
このため、ブラウザはアプリケーションを理解する必要がありません。 通常、JavaScript コードを指定してすべての動作を明示的にプログラムすることで、ブラウザーに理解させます。 現在は HTML のみが存在し、ブラウザはアプリケーションがどのように動作するか、その状態がどのようなものであるかについて事前の知識を必要としません。 HTML を画面上にレンダリングするだけでよく、HTML 自体がアプリケーションの状態をエンコードします。
このタイプのアーキテクチャは HATEOAS として知られており、これは「Hypermedia As The Engine Of Application State」の略です。 これは、状態転送の媒体としてハイパーメディアを使用する特殊なタイプの REST アーキテクチャであり、その同じハイパーメディアが、ユーザーがアプリケーションを新しい状態に駆動するためのインターフェイスになります。
さらに詳しく知りたい場合は、HTMX Web サイトにこのテーマに関する記事、エッセイ、講演の素晴らしいコレクションがあります。 この記事の目的として、HTML が WordPress 開発者にとって重要な理由に移りましょう。
HTMX <3 ワードプレス
WordPress は巨大なモノリシック PHP サーバーです。 WordPress プラグインも主に PHP で書かれています。 WordPress が提供する Hooks API や Database API などの PHP API を使用して、サイトに新しい機能を追加できます。 これらの API は JavaScript からは利用できないため、プラグイン開発者は、できるだけ多くのプラグイン コードをサーバー上に保持する必要があります。 HTMX を使用する動機があるとすれば、これです。
多くの点で、HTMX は WordPress 用に構築されました。 むしろ、WordPressのようなアプリケーションの場合です。 サーバー API のコレクションを残す必要がある外国語の負担を避けたいアプリケーション。 特に、ハイパーメディアを使用して単に状態を転送するだけで十分な場合はそうではありません。
WordPress プラグイン用の優れた UI の作成が容易になると、プラグインのエコシステムに劇的な影響を与える可能性があります。 無料のプラグインを維持する開発者は、ユーザーにとってより良いユーザー エクスペリエンスを構築することがより実現可能であると考えるかもしれません。また、小規模なチームは、節約された時間で機能をより速く反復できる可能性があります。 これは、さらに大きな予算をもつ大規模チームによって大きく支配されている市場において、小規模なプラグインの競争力を高めるのに役立ちます。
より大きなプラグインも特に興味を持つかもしれません。 JavaScript アプリは急激に成長する可能性があります。 HTMX を使用すると、これらのプラグインは大規模な JSON API と JavaScript アプリを削除し、WordPress API に完全にアクセスできる無駄のない HTML サーバーをその場所に残すことができます。
最終的な考え
私はしばらくの間、HTML MX を PHP や Go と一緒に使って遊んでいます。 これは、Web 上にユーザー インターフェイスを構築するための説得力のある代替手段を提供し、ハイパーメディアを使用してアプリケーションの状態を制御するための説得力のある議論を提供します。
プラグイン開発者の方は、必ず HTMX をチェックしてください。 この記事ではほんの表面をなぞっただけですが、ドキュメントは豊富な例とともに非常によく書かれています。 また、HTMX が最初から付属している機能を考えると、驚くほど短いです。 数分以内に HTMX と PHP を使い始めることができるはずです。