HTMX pourrait être un gros problème pour WordPress
Publié: 2024-05-10Créer une expérience utilisateur riche dans le navigateur peut être une tâche difficile, qui nécessite souvent une quantité importante de code JavaScript. À mesure que les besoins et les ambitions de notre application augmentent, la complexité de notre code JavaScript augmente également. Il n’est donc pas surprenant de voir à quelle fréquence les développeurs ont révisé notre façon de penser et d’écrire les applications JavaScript.
Jours depuis le dernier framework JS.
Les développeurs de plugins WordPress ont pire encore. L’environnement que nous ciblons n’est ni un serveur que nous contrôlons, ni un serveur disposant d’un contrôle total sur l’ensemble de la page. S'il est tout à fait possible d'utiliser avec succès un framework JavaScript dans un plugin WordPress, il peut également être remarquablement facile de se retrouver avec un projet dont l'ampleur et la complexité dépassent ce que vous aviez prévu ou attendu.
Mais et s’il n’était pas nécessaire qu’il en soit ainsi ? Dans cet article, nous explorerons comment les interfaces utilisateur Web modernes sont construites avec JavaScript, les difficultés auxquelles les développeurs sont confrontés et l'alternative offerte par HTMX. En particulier, nous examinerons pourquoi HTMX et WordPress peuvent être une combinaison parfaite.
Comment nous sommes arrivés ici
Avant JavaScript, les navigateurs n’étaient essentiellement que des lecteurs de documents glorifiés. En tant que telle, la plupart des expériences sur le Web étaient des « applications multipages », ou MPA en abrégé. Les MPA sont des applications Web composées de plusieurs documents HTML, un pour chaque page de l'application. Au fur et à mesure que l'utilisateur utilise l'application, différents documents lui sont présentés avec différentes actions disponibles.
Les AMP sont très simples à construire. La navigation se fait à l'aide de balises <a>
pour créer des liens vers d'autres documents, et les entrées de l'utilisateur peuvent être capturées avec un élément <form>
. Le serveur répond aux demandes de liens et de formulaires avec de nouveaux documents HTML, remplaçant la page affichée à l'écran.
Un bon exemple de MPA que vous connaissez probablement très bien est WP Admin. Chaque page d'administration est un document HTML généré par le code PHP WordPress exécuté sur le serveur. La plupart des pages de WP Admin, comme les pages de paramètres WordPress, ont tendance à être principalement composées de formulaires que vous, l'utilisateur, pouvez soumettre.
À l’inverse, une application monopage, ou SPA, est une application qui utilise une seule page HTML. La navigation et la saisie de l'utilisateur sont ensuite gérées par le code JavaScript, modifiant dynamiquement des parties de la page sur place sans avoir besoin de permuter la page entière ou de l'actualiser. Cela se traduit par une expérience utilisateur plus fluide et plus réactive.
De nos jours, de nombreuses applications Web utilisent des SPA pour leur interface Web. Chez RebelCode, nous avons construit des SPA pour les interfaces d'administration de nos deux principaux plugins WordPress : Spotlight et Aggregator. L’éditeur de site relativement nouveau de WordPress est également un SPA, tout comme l’éditeur de publication basé sur des blocs.
Le prix que nous payons
Les SPA sont leurs propres applications, écrites en JavaScript et exécutées dans le navigateur. Leur propre définition constitue également leur plus grande réserve : ils n’ont pas d’accès immédiat aux ressources du serveur. Cela signifie que nous devons établir un canal de communication entre le SPA et le serveur.
Créons un simple plugin WordPress pour utiliser un exemple. Ce plugin fournit
une interface utilisateur CRUD simple pour gérer les livres. L'API interne du plugin sur le serveur peut ressembler à ceci :
<?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;
Pour créer notre interface SPA moderne, nous utiliserons un framework JavaScript comme React ; le framework JavaScript le plus populaire également utilisé par WordPress. Commençons par ajouter une page d'administration :
<?php add_action('admin_menu', function () { add_menu_page('Books', 'Books', 'manage_options', 'books', 'books_page'); }); function books_page() { echo '<div></div>'; }
Notre page affichera un seul élément <div>
vide qui servira de racine à notre application React où le reste de l'interface utilisateur sera rendu.
const rootEl = document.getElementById("books-app"); const root = ReactDOM.createRoot(rootEl); root.render(<BooksApp />); function BooksApp() { return ( <div> <h1>My Books</h1> ... </div> ); }
Alors, comment listons-nous les livres stockés dans la base de données ? Le code pour faire cela se trouve sur le serveur, nous avons donc besoin d'un moyen de l'appeler et d'obtenir son résultat.
Pour ce faire, nous pouvons exposer une API JSON depuis le serveur. L'application React peut alors faire une requête à l'URL de notre API, recevoir les livres au format JSON, puis restituer la liste. Pour cet exemple, supposons que nous avons ajouté un point de terminaison à l'API REST WordPress :
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", }, ] }
Nous pouvons ensuite écrire un composant React qui récupère les livres et les restitue sous forme de liste :
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> ); }
Mais cette solution est trop naïve et donne une expérience utilisateur approximative. Il ne prend pas en compte les changements d'état après le démontage du composant, la mise en cache de la réponse, les nouvelles tentatives de requêtes ayant échoué ou l'empêchement d'un état obsolète d'écraser un état plus récent. En fait, la façon dont nous utilisons fetch()
dans un effet React est généralement déconseillée.
À bien des égards, cela peut être pire qu’une AMP traditionnelle. Donc, pour faire cela correctement, nous devrons implémenter quelques éléments supplémentaires dans notre client. Ou, de manière plus réaliste, utilisez des packages tiers.
Mais tout cela commence à ressembler à un effort disproportionné juste pour produire une liste de livres. Avons-nous vraiment besoin de créer une application JavaScript et une API JSON pour créer une expérience utilisateur fluide ?
Comparons cela avec un MPA, où le rendu de la liste des livres peut être réalisé en quelques lignes de code PHP, sans aucune dépendance :
<?php function render_books() { ?> <ul> <?php foreach (get_books() as $book): ?> <li> <a href="<?= $book->url ?>"> <?= $book->title ?> </a> </li> <?php endforeach; ?> </ul> <?php }
Mais bien entendu, cette comparaison n’est pas juste. Cette liste de livres n'est que du HTML statique ; il n'est pas réactif aux changements d'état ou aux entrées de l'utilisateur.
Si nous voulons avoir une expérience de type SPA tout en rendant le HTML sur le serveur, où notre code a un accès immédiat à la base de données, nous devrons trouver un moyen pour que le HTML rendu par le serveur trouve son chemin vers le navigateur. et remplace la liste de livres précédente. Mais y parvenir sans aucun code JavaScript est actuellement impossible, nous devrions donc serrer les dents et utiliser JavaScript de toute façon.
Mais nous n’avons pas besoin de l’écrire nous-mêmes.
Présentation de HTML
HTMX est une petite bibliothèque JavaScript qui fait principalement une chose : permettre à HTML de demander du nouveau HTML au serveur. Il le fait en utilisant de nouveaux attributs, qui nous permettent d'indiquer à HTMX d'où obtenir le nouveau code HTML, avec quoi l'échanger et ce qui déclenche l'échange. Il agit comme un pont entre notre serveur HTML et la page du navigateur.
Il s'agit d'une façon très différente de penser les SPA, puisque nous ne construisons pas d'application client JavaScript pour mettre à jour la page actuelle. Au lieu de cela, nous ajoutons simplement quelques attributs HTML pour indiquer à HTML comment nous souhaitons que la page change lorsque certains événements se produisent.
Même sans HTML, vous pouvez déjà modifier ce qui est affiché à l'écran en utilisant uniquement du HTML, bien que de manière très limitée. Vous connaissez déjà cette fonctionnalité HTML : le modeste élément de lien <a>
.
<a href="https://my-wp-site.com/books">View books</a>
Un élément de lien donne au navigateur toutes les informations nécessaires à la navigation. Lorsqu'on clique dessus, le navigateur prend le href
de l'élément, fait une requête à cette URL, télécharge la réponse et, en supposant qu'elle contient du HTML, remplace le contenu de la page par le nouveau HTML.
L'élément <form>
est un autre exemple de la manière dont HTML peut demander du nouveau HTML.
<form action="/contact.php"> <label> Your message: <input type="text" name="message" /> </label> <button type="submit">Send message</button> </form>
Cette fois, le navigateur collecte les valeurs de toutes les entrées du formulaire, les envoie au serveur, télécharge la réponse et l'affiche à l'écran.
Pourquoi seuls
Extrait du fichier Lisez-moi GitHub de HTMX<a>
et<form>
devraient-ils pouvoir effectuer des requêtes HTTP ? Pourquoi ne devriez-vous pouvoir remplacer que l’ intégralité de l’écran ?
Eh bien, HTML change cela.
<a href="https://my-wp-site.com/books" hx-target="#books"> View books </a> <div></div>
Avec l'attribut HTMX hx-target
, cliquer sur le lien placera désormais la réponse de https://my-wp-site.com/books
à l'intérieur de l'élément avec l'ID "books"
. Bien entendu, intégrer une page à l’intérieur d’une autre n’est pas le but ici. Notre serveur n'a pas besoin de répondre avec la page complète et peut simplement répondre avec un fragment HTML.
En exposant des fragments HTML de notre serveur et en indiquant à HTMX comment, d'où et quand obtenir ces fragments, nous pouvons créer une application Web de type SPA sans aucun JavaScript, où le serveur a un contrôle total. Dans un sens, HTML est devenu notre nouveau JSON.
Et tout ce que nous avons à faire est de charger le script HTMX dans notre page :
<script src="https://unpkg.com/[email protected]"></script>
(Assurez-vous de consulter la documentation HTMX pour obtenir des instructions, car le code ci-dessus peut être obsolète).
Regardons un autre exemple :
<button hx-get="/button/off" hx-target="this" hx-swap="outerHTML"> Turn off </button>
Il se passe beaucoup plus de choses ici, alors décomposons-les :
-
hx-get
spécifie l'URL à laquelle envoyer une requêteGET
lorsque l'on clique sur le bouton. -
hx-target="this"
indique à HTMX d'échanger le bouton cliqué avec la réponse. -
hx-swap="outerHTML"
indique à HTMX d'échanger l'intégralité du bouton, pas seulement ce qu'il contient.
Dans l'ensemble, cela indique à HTMX :
Lorsque vous cliquez sur le bouton, envoyez une requête GET à
/button/off
et remplacez ce bouton par la réponse.
Disons que le serveur répond à /button/off
avec le code HTML ci-dessous :
<button hx-get="/button/on" hx-target="this" hx-swap="outerHTML"> Turn on </button>
Pouvez-vous voir la différence? L'attribut hx-get
pointe désormais vers /button/on
et le texte à l'intérieur du bouton est désormais « Activer ». Lorsque ce bouton est cliqué, il sera également remplacé par la réponse de /button/on
. Comme vous pouvez l'imaginer, nous pouvons demander au serveur de répondre avec le bouton d'origine pour terminer notre bascule !
Cette idée simple de permettre à n'importe quel élément de demander du nouveau HTML au serveur et de décider où va ce HTML s'avère assez puissante. Nous pouvons créer des onglets, effectuer des recherches avec des résultats en direct, des barres de progression, etc.
Avantages et inconvénients
Contrairement à la plupart des frameworks JavaScript, HTMX ne nécessite pas que le code de notre application client soit compilé et regroupé. Cela constitue à lui seul un énorme avantage ; Les systèmes de construction JavaScript peuvent être notoirement difficiles à configurer et à maintenir, surtout lorsque vous commencez à introduire des fonctionnalités et des bibliothèques plus exotiques, comme TypeScript, JSX, les préprocesseurs CSS, etc. Il n'est pas rare qu'une équipe de taille moyenne à grande ait un ou plusieurs membres dédiés à cette tâche.
Un autre avantage évident est l’absence d’application client distincte. Puisque tout ce dont nous avons besoin est un serveur HTTP qui répond en HTML, nous pouvons utiliser n'importe quel langage de programmation que nous aimons. Cela peut être un argument de vente important pour vous si votre équipe n'est pas familiarisée avec le JavaScript moderne ou n'est pas assez grande pour justifier la création de deux applications. Cela peut être particulièrement tentant si vous êtes un développeur de plugin WordPress, puisque vous pouvez utiliser PHP pour tous les aspects de votre plugin.
Mais l’avantage le plus important est peut-être que vous n’avez plus besoin d’une API entre le back-end et le front-end de votre application. Cela peut permettre d'économiser énormément de temps de développement, ainsi que de réduire la quantité de code susceptible de produire des bogues, ce qui permet également de gagner du temps à long terme.
Cependant, nous ne devrions pas être naïfs au point de supposer qu’utiliser HTMX signifie ne pas avoir à écrire de JavaScript. Une certaine quantité de JavaScript peut encore être requise pour des tâches telles que le glisser-déposer, les graphiques, les sélecteurs de couleurs et de dates, etc. Bien que nous puissions toujours utiliser des solutions indépendantes du framework, telles que SortableJS et Floating UI. De plus, nous pourrions également constater que le besoin de JavaScript sera moindre à l'avenir, à mesure que les normes Web continueront d'évoluer avec de nouveaux éléments HTML, comme le récent élément <dialog>
.
Deuxièmement, ironiquement, PHP n'est pas très bon en matière de création de modèles HTML, bien qu'il ait été conçu pour cela. Sa syntaxe de balise est trop verbeuse et sa syntaxe de chaîne HEREDOC a une prise en charge limitée pour l'interpolation de chaîne.
Enfin, créer un point de terminaison dans WordPress n’est pas très simple. Considérez le plugin books des exemples précédents. Nous devons avoir un chemin sur le serveur qui répond avec la liste des livres sous forme HTML. Comment pouvons-nous enregistrer ce point de terminaison ?
- Détecter un paramètre GET lors de l'action
init
ouadmin_init
? - Utiliser l'API Admin Ajax ?
- Enregistrer un point de terminaison d'API REST ?
- Ajouter une règle de réécriture personnalisée ?
Il existe de nombreuses options, mais aucune ne rend les choses aussi simples qu'elles devraient l'être.
HAINE
Il y a un détail subtil dans notre exemple précédent qu’il est très facile de manquer, et il semblera probablement évident une fois signalé.
Lorsque nous obtenons le HTML du serveur, le bouton sur la page est soit la variante ON, soit la variante OFF. Selon celui affiché à l'écran, l'action de clic sera différente.
De ce fait, le navigateur n’a pas besoin de comprendre notre application. Nous ferions normalement comprendre au navigateur en donnant du code JavaScript pour programmer explicitement tous les comportements. Désormais, nous n'avons que HTML et le navigateur n'a besoin d'aucune connaissance préalable du comportement de notre application ou de son état. Il lui suffit d'afficher le code HTML à l'écran, qui code lui-même l'état de notre application.
Ce type d'architecture est connu sous le nom de HATEOAS, qui signifie « Hypermedia As The Engine Of Application State ». Il s'agit d'un type spécialisé d'architecture REST qui utilise l'hypermédia comme support de transfert d'état, et ce même hypermédia devient l'interface à travers laquelle l'utilisateur pilote l'application vers de nouveaux états.
Le site Web HTMX propose une grande collection d'articles, d'essais et de conférences sur ce sujet, si vous souhaitez en savoir plus. Pour les besoins de cet article, voyons pourquoi HTMX pourrait être un gros problème pour les développeurs WordPress.
HTML <3 WordPress
WordPress est un serveur PHP géant et monolithique. Les plugins WordPress sont également principalement écrits en PHP. Ils peuvent ajouter de nouvelles fonctionnalités au site à l'aide des API PHP fournies par WordPress, telles que l'API Hooks et l'API Database. Ces API ne sont pas disponibles à partir de JavaScript, les développeurs de plugins doivent donc souhaiter conserver autant que possible le code de leur plugin sur le serveur. S’il y a jamais eu une motivation pour utiliser HTMX, c’est bien celle-là !
À bien des égards, HTMX a été conçu pour WordPress. Ou plutôt, pour des applications comme WordPress ; des applications qui préfèrent ne pas être surchargées par une langue étrangère qui les oblige à abandonner leurs collections d'API de serveur. Surtout pas lorsqu’un simple transfert d’état via l’hypermédia serait suffisant.
Rendre plus facile la création de bonnes interfaces utilisateur pour les plugins WordPress peut avoir un impact considérable sur l’écosystème des plugins. Les développeurs qui gèrent des plugins gratuits peuvent trouver plus facile de créer de meilleures expériences utilisateur pour leurs utilisateurs, et les petites équipes peuvent être en mesure d'itérer plus rapidement sur les fonctionnalités avec le temps gagné. Cela peut contribuer à rendre les petits plugins plus compétitifs sur un marché fortement dominé par de grandes équipes dotées de budgets encore plus importants.
Les plugins plus volumineux peuvent également être particulièrement intéressés. Les applications JavaScript peuvent croître à une vitesse exponentielle. HTMX pourrait permettre à ces plugins de supprimer leurs massives API JSON et applications JavaScript, et de laisser à leur place un serveur HTML léger ayant un accès complet aux API WordPress.
Dernières pensées
Je joue avec HTMX depuis un moment maintenant, en l'utilisant avec PHP et Go. Il offre une alternative intéressante pour créer des interfaces utilisateur sur le Web et un argument convaincant en faveur de l'utilisation de l'hypermédia pour piloter l'état des applications.
Si vous êtes un développeur de plugins, assurez-vous de consulter HTMX. Nous avons à peine effleuré la surface dans cet article et la documentation est très bien écrite et contient de nombreux exemples. Il est également étonnamment court, compte tenu de la quantité de HTMX fourni par défaut. Vous devriez pouvoir démarrer avec HTMX et PHP en quelques minutes.