HTMX könnte eine große Sache für WordPress sein
Veröffentlicht: 2024-05-10Der Aufbau eines umfassenden Benutzererlebnisses im Browser kann eine anspruchsvolle Aufgabe sein, die oft eine erhebliche Menge an JavaScript-Code erfordert. Mit steigenden Anforderungen und Ambitionen unserer Anwendung wächst auch die Komplexität unseres JavaScript-Codes. Es ist daher nicht verwunderlich, wie oft Entwickler unsere Denkweise und das Schreiben von JavaScript-Apps überarbeitet haben.
Tage seit dem letzten JS-Framework.
Entwickler von WordPress-Plugins haben es noch schlimmer. Die Umgebung, auf die wir abzielen, ist weder ein Server, den wir kontrollieren, noch einer mit vollständiger Kontrolle über die gesamte Seite. Während es durchaus möglich ist, ein JavaScript-Framework erfolgreich in einem WordPress-Plugin zu verwenden, kann es auch bemerkenswert einfach sein, am Ende ein Projekt zu erhalten, dessen Umfang und Komplexität über das hinausgehen, was Sie beabsichtigt oder erwartet haben.
Aber was wäre, wenn es nicht so sein müsste? In diesem Artikel untersuchen wir, wie moderne Web-Benutzeroberflächen mit JavaScript erstellt werden, welche Schwierigkeiten Entwickler haben und welche Alternative HTMX bietet. Insbesondere werfen wir einen Blick darauf, warum HTMX und WordPress eine himmlische Kombination sein könnten.
Wie wir hierher gekommen sind
Vor JavaScript waren Browser im Grunde nur verherrlichte Dokumentleser. Daher handelte es sich bei den meisten Erlebnissen im Web um „Multi-Page Applications“, kurz MPAs. MPAs sind Webanwendungen, die aus mehreren HTML-Dokumenten bestehen, eines für jede Seite in der Anwendung. Während der Benutzer die Anwendung verwendet, werden ihm verschiedene Dokumente mit unterschiedlichen verfügbaren Aktionen angezeigt.
MPAs sind sehr einfach zu bauen. Die Navigation erfolgt über <a>
-Tags, um Links zu anderen Dokumenten herzustellen, und Benutzereingaben können mit einem <form>
-Element erfasst werden. Der Server antwortet auf Link- und Formularanfragen mit neuen HTML-Dokumenten und ersetzt die Seite, die auf dem Bildschirm angezeigt wird.
Ein gutes Beispiel für einen MPA, mit dem Sie wahrscheinlich sehr vertraut sind, ist WP Admin. Jede Admin-Seite ist ein Dokument mit HTML, das vom WordPress-PHP-Code generiert wird, der auf dem Server ausgeführt wird. Die meisten Seiten in WP Admin, wie z. B. die WordPress-Einstellungsseiten, bestehen hauptsächlich aus Formularen, die Sie als Benutzer einreichen können.
Im Gegensatz dazu ist eine Single-Page-Anwendung oder SPA eine Anwendung, die eine einzelne HTML-Seite verwendet. Navigation und Benutzereingaben werden dann von JavaScript-Code verarbeitet, wodurch Teile der Seite dynamisch direkt geändert werden, ohne dass die gesamte Seite ausgetauscht oder aktualisiert werden muss. Dies führt zu einem reibungsloseren und reaktionsschnelleren Benutzererlebnis.
Heutzutage verwenden viele Webanwendungen SPAs für ihre Weboberfläche. Bei RebelCode haben wir SPAs für die Admin-Schnittstellen unserer beiden wichtigsten WordPress-Plugins erstellt: Spotlight und Aggregator. Auch der relativ neue Site-Editor in WordPress ist ein SPA, ebenso wie der blockbasierte Post-Editor.
Der Preis, den wir zahlen
SPAs sind eigene Anwendungen, die in JavaScript geschrieben sind und im Browser ausgeführt werden. Ihre eigene Definition ist auch ihr größter Vorbehalt: Sie haben keinen unmittelbaren Zugriff auf Serverressourcen. Das bedeutet, dass wir einen Kommunikationskanal zwischen dem SPA und dem Server einrichten müssen.
Lassen Sie uns als Beispiel ein einfaches WordPress-Plugin erstellen. Dieses Plugin bietet
eine einfache CRUD-Benutzeroberfläche zum Verwalten von Büchern. Die interne API des Plugins auf dem Server könnte etwa so aussehen:
<?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;
Um unsere moderne SPA-Schnittstelle zu erstellen, verwenden wir ein JavaScript-Framework wie React; das beliebteste JavaScript-Framework, das auch von WordPress verwendet wird. Beginnen wir mit dem Hinzufügen einer Admin-Seite:
<?php add_action('admin_menu', function () { add_menu_page('Books', 'Books', 'manage_options', 'books', 'books_page'); }); function books_page() { echo '<div></div>'; }
Unsere Seite rendert ein einzelnes, leeres <div>
-Element, das als Stamm unserer React-Anwendung dient, wo der Rest der Benutzeroberfläche gerendert wird.
const rootEl = document.getElementById("books-app"); const root = ReactDOM.createRoot(rootEl); root.render(<BooksApp />); function BooksApp() { return ( <div> <h1>My Books</h1> ... </div> ); }
Wie listen wir also die Bücher auf, die in der Datenbank gespeichert sind? Der Code dafür befindet sich auf dem Server, daher brauchen wir eine Möglichkeit, ihn aufzurufen und das Ergebnis zu erhalten.
Dazu können wir eine JSON-API vom Server aus bereitstellen. Die React-App kann dann eine Anfrage an die URL unserer API stellen, die Bücher im JSON-Format empfangen und dann die Liste rendern. Nehmen wir für dieses Beispiel an, dass wir der WordPress-REST-API einen Endpunkt hinzugefügt haben:
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", }, ] }
Anschließend können wir eine React-Komponente schreiben, die die Bücher abruft und als Liste darstellt:
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> ); }
Diese Lösung ist jedoch zu naiv und führt zu einer groben Benutzererfahrung. Statusänderungen nach dem Aufheben der Bereitstellung der Komponente werden nicht berücksichtigt, die Antwort wird nicht zwischengespeichert, fehlgeschlagene Abfragen werden nicht wiederholt und es wird auch nicht verhindert, dass ein veralteter Status einen neueren Status überschreibt. Tatsächlich wird von der Art und Weise, wie wir fetch()
in einem React-Effekt verwenden, generell abgeraten.
In vielerlei Hinsicht kann dies schlimmer sein als eine herkömmliche MPA. Um dies richtig zu machen, müssen wir noch ein paar weitere Dinge in unserem Client implementieren. Oder realistischer: Verwenden Sie Pakete von Drittanbietern.
Aber all dies scheint ein unverhältnismäßig großer Aufwand zu sein, nur um eine Liste von Büchern zu erstellen. Müssen wir wirklich eine JavaScript-App und eine JSON-API erstellen, um ein reibungsloses Benutzererlebnis zu schaffen?
Vergleichen wir dies mit einem MPA, bei dem das Rendern der Buchliste in nur wenigen Zeilen PHP-Code ohne Abhängigkeiten erfolgen kann:
<?php function render_books() { ?> <ul> <?php foreach (get_books() as $book): ?> <li> <a href="<?= $book->url ?>"> <?= $book->title ?> </a> </li> <?php endforeach; ?> </ul> <?php }
Aber das ist natürlich kein fairer Vergleich. Bei dieser Bücherliste handelt es sich lediglich um statisches HTML. Es reagiert nicht auf Zustandsänderungen oder Benutzereingaben.
Wenn wir ein SPA-ähnliches Erlebnis haben und gleichzeitig den HTML-Code auf dem Server rendern möchten, wo unser Code direkten Zugriff auf die Datenbank hat, müssen wir einen Weg finden, damit der vom Server gerenderte HTML-Code seinen Weg zum Browser findet und ersetzen Sie die vorherige Liste der Bücher. Aber ohne jeglichen JavaScript-Code ist dies derzeit nicht möglich, sodass wir ohnehin in den sauren Apfel beißen und JavaScript verwenden müssten.
Aber wir müssen es nicht selbst schreiben.
Wir stellen HTMX vor
HTMX ist eine kleine JavaScript-Bibliothek, die in erster Linie eines tut: HTML erlauben, neues HTML vom Server anzufordern. Dies geschieht mithilfe neuer Attribute, die es uns ermöglichen, HTMX mitzuteilen, woher der neue HTML-Code stammt, womit er ausgetauscht werden soll und was den Austausch auslöst. Es fungiert als Brücke zwischen unserem HTML-Server und der Seite im Browser.
Dies ist eine völlig andere Denkweise über SPAs, da wir keine Client-JavaScript-Anwendung erstellen, um die aktuelle Seite zu aktualisieren. Stattdessen fügen wir einfach einige HTML-Attribute hinzu, um HTMX mitzuteilen, wie sich die Seite ändern soll, wenn bestimmte Ereignisse eintreten.
Auch ohne HTMX können Sie bereits mit HTML die Darstellung auf dem Bildschirm ändern, wenn auch in sehr begrenztem Umfang. Sie kennen diese HTML-Funktion bereits: das bescheidene Linkelement <a>
.
<a href="https://my-wp-site.com/books">View books</a>
Ein Link-Element liefert dem Browser alle Informationen, die für die Navigation erforderlich sind. Wenn darauf geklickt wird, entnimmt der Browser die href
des Elements, stellt eine Anfrage an diese URL, lädt die Antwort herunter und ersetzt, vorausgesetzt, dass sie HTML enthielt, den Inhalt der Seite durch den neuen HTML-Code.
Das <form>
-Element ist ein weiteres Beispiel dafür, wie HTML neues HTML anfordern kann.
<form action="/contact.php"> <label> Your message: <input type="text" name="message" /> </label> <button type="submit">Send message</button> </form>
Diesmal sammelt der Browser die Werte aller Eingaben im Formular, sendet sie an den Server, lädt die Antwort herunter und stellt sie auf dem Bildschirm dar.
Warum sollten nur
Aus der GitHub-Readme-Datei von HTMX<a>
und<form>
HTTP-Anfragen stellen können? Warum sollte man nur den gesamten Bildschirm austauschen können?
Nun, HTMX ändert das.
<a href="https://my-wp-site.com/books" hx-target="#books"> View books </a> <div></div>
Mit dem HTMX- hx-target
Attribut wird durch Klicken auf den Link nun die Antwort von https://my-wp-site.com/books
innerhalb des Elements mit der ID "books"
platziert. Natürlich ist es hier nicht das Ziel, eine Seite in eine andere einzubetten. Unser Server muss nicht mit der gesamten Seite antworten, sondern kann stattdessen einfach mit einem HTML-Fragment antworten.
Indem wir HTML-Fragmente von unserem Server verfügbar machen und HTMX mitteilen, wie, von wo und wann diese Fragmente abgerufen werden sollen, können wir eine SPA-ähnliche Webanwendung ohne JavaScript erstellen, bei der der Server die volle Kontrolle hat. In gewisser Weise ist HTML zu unserem neuen JSON geworden.
Und alles was wir tun müssen, ist das HTMX-Skript in unsere Seite zu laden:
<script src="https://unpkg.com/[email protected]"></script>
(Anweisungen finden Sie unbedingt in der HTMX-Dokumentation, da der obige Code möglicherweise veraltet ist.)
Schauen wir uns ein anderes Beispiel an:
<button hx-get="/button/off" hx-target="this" hx-swap="outerHTML"> Turn off </button>
Hier ist noch viel mehr los, also lasst es uns aufschlüsseln:
-
hx-get
gibt die URL an, an die eineGET
Anfrage gesendet werden soll, wenn auf die Schaltfläche geklickt wird. -
hx-target="this"
weist HTMX an, die angeklickte Schaltfläche mit der Antwort auszutauschen. -
hx-swap="outerHTML"
weist HTMX an, die gesamte Schaltfläche auszutauschen, nicht nur den Inhalt.
Alles in allem sagt dies HTMX:
Wenn auf die Schaltfläche geklickt wird, senden Sie eine GET-Anfrage an
/button/off
und ersetzen Sie diese Schaltfläche durch die Antwort.
Nehmen wir an, der Server antwortet auf /button/off
mit dem folgenden HTML:
<button hx-get="/button/on" hx-target="this" hx-swap="outerHTML"> Turn on </button>
Kannst du den Unterschied erkennen? Das hx-get
Attribut zeigt jetzt auf /button/on
und der Text innerhalb der Schaltfläche lautet jetzt „Turn on“. Wenn auf diese Schaltfläche geklickt wird, wird sie auch durch die Antwort von /button/on
ersetzt. Wie Sie sich vorstellen können, können wir den Server veranlassen, mit der ursprünglichen Schaltfläche zu antworten, um unsere Umschaltung abzuschließen!
Diese einfache Idee, jedem Element zu erlauben, neuen HTML-Code vom Server anzufordern und zu entscheiden, wohin dieser HTML-Code verschoben wird, erweist sich als ziemlich wirkungsvoll. Wir können Registerkarten erstellen, mit Live-Ergebnissen, Fortschrittsbalken und mehr suchen.
Vor-und Nachteile
Im Gegensatz zu den meisten JavaScript-Frameworks erfordert HTMX nicht, dass unser Client-Anwendungscode kompiliert und gebündelt wird. Dies allein ist ein enormer Vorteil; Es kann bekanntermaßen schwierig sein, JavaScript-Build-Systeme einzurichten und zu warten, insbesondere wenn Sie beginnen, exotischere Funktionen und Bibliotheken wie TypeScript, JSX, CSS-Präprozessoren usw. einzuführen. Das ist bei mittelgroßen bis großen Teams keine Seltenheit ein oder mehrere Mitglieder, die sich dieser Aufgabe widmen.
Ein weiterer offensichtlicher Vorteil ist das Fehlen einer separaten Client-Anwendung. Da wir lediglich einen HTTP-Server benötigen, der mit HTML antwortet, können wir jede beliebige Programmiersprache verwenden. Dies kann ein wichtiges Verkaufsargument für Sie sein, wenn Ihr Team nicht mit modernem JavaScript vertraut ist oder nicht groß genug ist, um die Entwicklung von zwei Anwendungen zu rechtfertigen. Dies kann besonders verlockend sein, wenn Sie ein WordPress-Plugin-Entwickler sind, da Sie PHP für alle Aspekte Ihres Plugins verwenden können.
Der vielleicht wichtigste Vorteil besteht jedoch darin, dass Sie keine API mehr zwischen dem Back-End und dem Front-End Ihrer Anwendung benötigen. Dies kann enorm viel Entwicklungszeit einsparen und die Menge an Code reduzieren, die Fehler verursachen kann, was auf lange Sicht auch Zeit spart.
Allerdings sollten wir nicht so naiv sein anzunehmen, dass die Verwendung von HTMX bedeutet, kein JavaScript schreiben zu müssen. Für Dinge wie Drag-and-Drop, Diagramme, Farb- und Datumsauswahl usw. ist möglicherweise immer noch eine gewisse Menge JavaScript erforderlich. Allerdings können wir jederzeit Framework-unabhängige Lösungen wie SortableJS und Floating UI verwenden. Darüber hinaus werden wir möglicherweise in Zukunft weniger Bedarf an JavaScript sehen, da sich Webstandards mit neuen HTML-Elementen, wie dem jüngsten <dialog>
-Element, weiterentwickeln.
Zweitens ist PHP ironischerweise nicht sehr gut im HTML-Templating, obwohl es genau dafür entwickelt wurde. Seine Tag-Syntax ist übermäßig ausführlich und seine HEREDOC-String-Syntax bietet nur begrenzte Unterstützung für String-Interpolation.
Schließlich ist das Erstellen eines Endpunkts in WordPress nicht ganz einfach. Betrachten Sie das Bücher-Plugin aus den vorherigen Beispielen. Wir benötigen einen Pfad auf dem Server, der mit der Liste der Bücher in HTML-Form antwortet. Wie registrieren wir diesen Endpunkt?
- Erkennen Sie einen GET-Parameter während der Aktion
init
oderadmin_init
? - Verwenden Sie die Admin-Ajax-API?
- Einen REST-API-Endpunkt registrieren?
- Eine benutzerdefinierte Umschreiberegel hinzufügen?
Es gibt viele Optionen, aber keine macht es so einfach, wie es sein sollte.
HATEOAS
In unserem vorherigen Beispiel gibt es ein subtiles Detail, das sehr leicht zu übersehen ist und das wahrscheinlich offensichtlich klingen wird, wenn man es einmal hervorgehoben hat.
Wenn wir den HTML-Code vom Server erhalten, ist die Schaltfläche auf der Seite entweder die ON-Variante oder die OFF-Variante. Je nachdem, welche auf dem Bildschirm angezeigt wird, ist die Klickaktion unterschiedlich.
Aus diesem Grund muss der Browser unsere Anwendung nicht verstehen. Normalerweise machen wir den Browser verständlich, indem wir JavaScript-Code bereitstellen, um alle Verhaltensweisen explizit zu programmieren. Jetzt haben wir nur noch HTML und der Browser benötigt keine Vorkenntnisse darüber, wie sich unsere Anwendung verhält oder welchen Status sie hat. Es muss lediglich der HTML-Code auf dem Bildschirm gerendert werden, der selbst den Status unserer Anwendung codiert.
Diese Art von Architektur ist als HATEOAS bekannt, was für „Hypermedia As The Engine Of Application State“ steht. Es handelt sich um eine spezielle Art von REST-Architektur, die Hypermedia als Medium für die Zustandsübertragung verwendet und dasselbe Hypermedia zur Schnittstelle wird, über die der Benutzer die Anwendung in neue Zustände steuert.
Auf der HTMX-Website finden Sie eine großartige Sammlung von Artikeln, Aufsätzen und Vorträgen zu diesem Thema, falls Sie mehr erfahren möchten. In diesem Artikel wollen wir uns mit der Frage befassen, warum HTMX für WordPress-Entwickler eine große Sache sein könnte.
HTMX <3 WordPress
WordPress ist ein riesiger, monolithischer PHP-Server. Auch WordPress-Plugins werden überwiegend in PHP geschrieben. Mithilfe der von WordPress bereitgestellten PHP-APIs wie der Hooks-API und der Datenbank-API können sie der Website neue Funktionen hinzufügen. Diese APIs sind in JavaScript nicht verfügbar, daher sollten Plugin-Entwickler so viel wie möglich von ihrem Plugin-Code auf dem Server belassen. Wenn es jemals eine Motivation gab, HTMX zu verwenden, dann ist es diese!
HTMX wurde in vielerlei Hinsicht für WordPress entwickelt. Oder besser gesagt, für Anwendungen wie WordPress; Anwendungen, die lieber nicht mit einer Fremdsprache belastet werden möchten, die sie dazu zwingt, ihre Sammlungen von Server-APIs zurückzulassen. Vor allem nicht, wenn die einfache Übertragung des Zustands mithilfe von Hypermedia ausreichen würde.
Die einfachere Erstellung guter Benutzeroberflächen für WordPress-Plugins kann dramatische Auswirkungen auf das Plugin-Ökosystem haben. Entwickler, die kostenlose Plugins anbieten, finden es möglicherweise einfacher, eine bessere Benutzererfahrung für ihre Benutzer zu schaffen, und kleinere Teams können durch die eingesparte Zeit möglicherweise schneller an Funktionen arbeiten. Dies kann dazu beitragen, kleinere Plugins in einem Markt, der stark von großen Teams mit noch größeren Budgets dominiert wird, wettbewerbsfähiger zu machen.
Auch größere Plugins könnten von besonderem Interesse sein. JavaScript-Apps können exponentiell schnell wachsen. HTMX könnte es diesen Plugins ermöglichen, ihre umfangreichen JSON-APIs und JavaScript-Apps zu entfernen und an ihrer Stelle einen schlanken HTML-Server zu belassen, der vollen Zugriff auf die WordPress-APIs hat.
Abschließende Gedanken
Ich experimentiere schon seit einiger Zeit mit HTMX herum und verwende es mit PHP und Go. Es bietet eine überzeugende Alternative zum Erstellen von Benutzeroberflächen im Web und ein überzeugendes Argument für die Verwendung von Hypermedia zur Steuerung des Anwendungsstatus.
Wenn Sie Plugin-Entwickler sind, schauen Sie sich unbedingt HTMX an. Wir haben in diesem Artikel kaum an der Oberfläche gekratzt und die Dokumentation ist sehr gut geschrieben und enthält viele Beispiele. Es ist auch überraschend kurz, wenn man bedenkt, wie viel HTMX im Lieferumfang enthalten ist. Sie sollten in wenigen Minuten in der Lage sein, mit HTMX und PHP zu beginnen.