HTMX ar putea fi o mare afacere pentru WordPress
Publicat: 2024-05-10Crearea unei experiențe de utilizator bogate în browser poate fi o sarcină dificilă, una care necesită adesea o cantitate semnificativă de cod JavaScript. Pe măsură ce nevoile și ambițiile aplicației noastre cresc, la fel crește și complexitatea codului nostru JavaScript. Prin urmare, nu este surprinzător cât de des dezvoltatorii au revizuit modul în care gândim și scriem aplicațiile JavaScript.
Zile de la ultimul cadru JS.
Dezvoltatorii de pluginuri WordPress o au mai rău. Mediul pe care îl vizam nu este nici un server pe care îl controlăm, nici unul cu control complet asupra întregii pagini. Deși este foarte posibil să utilizați cu succes un cadru JavaScript într-un plugin WordPress, poate fi, de asemenea, remarcabil de ușor să ajungeți la un proiect a cărui amploare și complexitate depășesc ceea ce v-ați dorit sau așteptați.
Dar dacă nu ar trebui să fie așa? În acest articol, vom explora modul în care interfețele web moderne sunt construite cu JavaScript, dificultățile cu care se confruntă dezvoltatorii și alternativa oferită de HTMX. În special, vom arunca o privire la motivul pentru care HTMX și WordPress pot fi o potrivire făcută în rai.
Cum am ajuns aici
Înainte de JavaScript, browserele erau practic doar cititori de documente glorificați. Ca atare, majoritatea experiențelor de pe web au fost „aplicații cu mai multe pagini” sau, pe scurt, MPA. MPA-urile sunt aplicații web care constau din mai multe documente HTML, câte unul pentru fiecare pagină din aplicație. Pe măsură ce utilizatorul folosește aplicația, li se arată diferite documente cu diferite acțiuni disponibile.
APM-urile sunt foarte ușor de construit. Navigarea se face utilizând etichete <a>
pentru a lega alte documente, iar intrarea utilizatorului poate fi capturată cu un element <form>
. Serverul răspunde solicitărilor de linkuri și formulare cu noi documente HTML, înlocuind pagina care este afișată pe ecran.
Un bun exemplu de MPA cu care probabil sunteți foarte familiarizat este WP Admin. Fiecare pagină de administrare este un document cu HTML care este generat de codul PHP WordPress care rulează pe server. Majoritatea paginilor din WP Admin, cum ar fi paginile de setări WordPress, tind să fie compuse în mare parte din formulare pe care tu, utilizatorul, le poți trimite.
În schimb, o aplicație cu o singură pagină, sau SPA, este o aplicație care utilizează o singură pagină HTML. Navigarea și introducerea utilizatorului sunt apoi gestionate de codul JavaScript, schimbând dinamic părți ale paginii în loc, fără a fi nevoie să schimbați întreaga pagină sau să o reîmprospătați. Acest lucru are ca rezultat o experiență de utilizator mai fluidă și mai receptivă.
În zilele noastre, multe aplicații web folosesc SPA-uri pentru interfața lor web. La RebelCode, am creat SPA-uri pentru interfețele de administrare ale celor două plugin-uri WordPress principale: Spotlight și Aggregator. Editorul de site relativ nou din WordPress este, de asemenea, un SPA, la fel ca și editorul de postări bazat pe blocuri.
Pretul pe care il platim
SPA-urile sunt propriile aplicații, scrise în JavaScript și rulând în browser. Definiția lor este și cea mai mare avertizare: nu au acces imediat la resursele serverului. Aceasta înseamnă că trebuie să stabilim un canal de comunicare între SPA și server.
Să creăm un plugin WordPress simplu pentru a folosi un exemplu. Acest plugin oferă
o interfață de utilizator CRUD simplă pentru gestionarea cărților. API-ul intern al pluginului de pe server poate arăta cam așa:
<?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;
Pentru a crea interfața noastră SPA modernă, vom folosi un cadru JavaScript precum React; cel mai popular cadru JavaScript care este folosit și de WordPress. Să începem prin a adăuga o pagină de administrator:
<?php add_action('admin_menu', function () { add_menu_page('Books', 'Books', 'manage_options', 'books', 'books_page'); }); function books_page() { echo '<div></div>'; }
Pagina noastră va reda un singur element <div>
gol, care va servi drept rădăcină a aplicației noastre React, unde va fi redat restul interfeței de utilizare.
const rootEl = document.getElementById("books-app"); const root = ReactDOM.createRoot(rootEl); root.render(<BooksApp />); function BooksApp() { return ( <div> <h1>My Books</h1> ... </div> ); }
Deci, cum listăm cărțile care sunt stocate în baza de date? Codul pentru a face asta se află pe server, așa că avem nevoie de o modalitate de a-l apela și de a obține rezultatul.
Pentru a face asta, putem expune un API JSON de pe server. Aplicația React poate face apoi o solicitare la adresa URL a API-ului nostru, poate primi cărțile în format JSON, apoi poate reda lista. Pentru acest exemplu, să presupunem că am adăugat un punct final la API-ul 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", }, ] }
Apoi putem scrie o componentă React care preia cărțile și le redă ca o listă:
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> ); }
Dar această soluție este prea naivă și oferă o experiență dură pentru utilizator. Nu ține cont de schimbările de stare după demontarea componentei, memorarea în cache a răspunsului, reîncercarea de interogări eșuate sau împiedicarea stării învechite să suprascrie starea mai recentă. De fapt, modul în care folosim fetch()
într-un efect React este în general descurajat.
În multe privințe, acest lucru poate fi mai rău decât un MPA tradițional. Deci, pentru a face acest lucru corect, va trebui să implementăm câteva lucruri în clientul nostru. Sau, mai realist, utilizați pachete terță parte.
Dar toate acestea încep să pară un efort disproporționat doar pentru a reda o listă de cărți. Chiar trebuie să creăm o aplicație JavaScript și un API JSON pentru a crea o experiență de utilizator fluidă?
Să comparăm asta cu un MPA, unde redarea listei de cărți poate fi realizată în doar câteva rânduri de cod PHP, fără nicio dependență:
<?php function render_books() { ?> <ul> <?php foreach (get_books() as $book): ?> <li> <a href="<?= $book->url ?>"> <?= $book->title ?> </a> </li> <?php endforeach; ?> </ul> <?php }
Dar, desigur, aceasta nu este o comparație corectă. Această listă de cărți este doar HTML static; nu este reactiv la modificările de stare sau la intrarea utilizatorului.
Dacă dorim să avem o experiență asemănătoare SPA, în timp ce redăm codul HTML pe server, unde codul nostru are acces imediat la baza de date, va trebui să găsim o modalitate prin care HTML-ul redat de server să-și găsească drumul către browser. și înlocuiți lista anterioară de cărți. Dar realizarea acestui lucru fără niciun cod JavaScript este în prezent imposibilă, așa că ar trebui să mușcăm glonțul și să folosim JavaScript oricum.
Dar nu trebuie să o scriem noi înșine.
Vă prezentăm HTMX
HTMX este o mică bibliotecă JavaScript care face în primul rând un lucru: permite HTML să solicite HTML nou de la server. Face acest lucru folosind noi atribute, care ne permit să spunem HTMX de unde să obținem noul HTML, cu ce să-l schimbăm și ce declanșează schimbarea. Acționează ca o punte între serverul nostru HTML și pagina din browser.
Acesta este un mod foarte diferit de a gândi SPA-uri, deoarece nu construim o aplicație JavaScript pentru client pentru a actualiza pagina curentă. În schimb, pur și simplu adăugăm câteva atribute HTML pentru a spune HTMX cum vrem să se schimbe pagina atunci când au loc anumite evenimente.
Chiar și fără HTMX, puteți deja modifica ceea ce este afișat pe ecran folosind doar HTML, deși într-un mod foarte limitat. Sunteți deja familiarizați cu această caracteristică HTML: umilul element de legătură <a>
.
<a href="https://my-wp-site.com/books">View books</a>
Un element de legătură oferă browserului toate informațiile necesare pentru efectuarea navigării. Când se face clic pe acesta, browserul preia href
din element, face o solicitare la adresa URL respectivă, descarcă răspunsul și, presupunând că acesta conține HTML, înlocuiește conținutul paginii cu noul HTML.
Elementul <form>
este un alt exemplu al modului în care HTML poate solicita HTML nou.
<form action="/contact.php"> <label> Your message: <input type="text" name="message" /> </label> <button type="submit">Send message</button> </form>
De data aceasta, browserul colectează valorile din toate intrările din formular, le trimite la server, descarcă răspunsul și îl redă pe ecran.
De ce ar trebui doar
Din cititorul GitHub de la HTMX<a>
și<form>
să poată face solicitări HTTP? De ce ar trebui să poți înlocui doar întregul ecran?
Ei bine, HTMX schimbă asta.
<a href="https://my-wp-site.com/books" hx-target="#books"> View books </a> <div></div>
Cu atributul HTMX hx-target
, făcând clic pe link, răspunsul de la https://my-wp-site.com/books
va fi plasat în interiorul elementului cu ID-ul "books"
. Desigur, încorporarea unei pagini în alta nu este scopul aici. Serverul nostru nu trebuie să răspundă cu pagina completă și poate răspunde doar cu un fragment HTML.
Expunând fragmente HTML de pe serverul nostru și spunându-i lui HTMX cum, de unde și când să obținem acele fragmente, putem crea o aplicație web asemănătoare SPA fără JavaScript, unde serverul are control deplin. Într-un fel, HTML a devenit noul nostru JSON.
Și tot ce trebuie să facem este să încărcăm scriptul HTMX în pagina noastră:
<script src="https://unpkg.com/[email protected]"></script>
(Asigurați-vă că consultați documentația HTMX pentru instrucțiuni, deoarece codul de mai sus poate fi învechit).
Să ne uităm la un alt exemplu:
<button hx-get="/button/off" hx-target="this" hx-swap="outerHTML"> Turn off </button>
Se întâmplă mult mai multe aici, așa că haideți să le dezvăluim:
-
hx-get
specifică adresa URL la care se trimite o solicitareGET
atunci când se face clic pe butonul. -
hx-target="this"
îi spune lui HTMX să schimbe butonul apăsat cu răspunsul. -
hx-swap="outerHTML"
îi spune lui HTMX să schimbe întregul buton, nu doar ceea ce este înăuntrul acestuia.
Toate împreună, aceasta îi spune lui HTMX:
Când se face clic pe butonul, trimiteți o solicitare GET la
/button/off
și înlocuiți acest buton cu răspunsul.
Să presupunem că serverul răspunde la /button/off
cu HTML-ul de mai jos:
<button hx-get="/button/on" hx-target="this" hx-swap="outerHTML"> Turn on </button>
Poți vedea diferența? Atributul hx-get
indică acum către /button/on
iar textul din interiorul butonului este acum „Pornire”. Când se face clic pe acest buton, acesta va fi înlocuit și cu răspunsul de la /button/on
. După cum vă puteți imagina, putem pune serverul să răspundă cu butonul original pentru a finaliza comutarea!
Această idee simplă de a permite oricărui element să solicite HTML nou de la server și să decidă unde merge acel HTML se dovedește a fi destul de puternică. Putem crea file, căuta cu rezultate live, bare de progres și multe altele.
Argumente pro şi contra
Spre deosebire de majoritatea cadrelor JavaScript, HTMX nu necesită compilarea și combinarea codului aplicației noastre client. Numai acest lucru este un beneficiu imens; Sistemele de compilare JavaScript pot fi notoriu de dificil de configurat și întreținut, mai ales că începi să introduci funcții și biblioteci mai exotice, cum ar fi TypeScript, JSX, preprocesoare CSS etc. Nu este neobișnuit ca echipele medii spre mari să aibă unul sau mai mulți membri dedicați acestei sarcini.
Un alt beneficiu evident este lipsa unei aplicații client separate. Deoarece tot ce avem nevoie este un server HTTP care să răspundă cu HTML, putem folosi orice limbaj de programare care ne place. Acesta poate fi un motiv de vânzare pentru dvs. dacă echipa dvs. nu este familiarizată cu JavaScript modern sau nu este suficient de mare pentru a justifica construirea a două aplicații. Poate fi mai ales tentant dacă sunteți un dezvoltator de plugin WordPress, deoarece puteți utiliza PHP pentru toate aspectele pluginului dvs.
Dar poate cel mai important beneficiu este că nu mai aveți nevoie de un API între back-end și front-end al aplicației dvs. Acest lucru poate economisi o cantitate enormă de timp de dezvoltare, precum și poate reduce cantitatea de cod care poate produce erori, ceea ce economisește și timp pe termen lung.
Cu toate acestea, nu ar trebui să fim atât de naivi încât să presupunem că folosirea HTMX înseamnă că nu trebuie să scriem JavaScript . Este posibil să fie necesară încă o anumită cantitate de JavaScript pentru lucruri precum tragerea și plasarea, diagrame, alegeri de culori și date și așa mai departe. Deși putem folosi întotdeauna soluții independente de cadru, cum ar fi SortableJS și Floating UI. În plus, este posibil să găsim mai puțină nevoie de JavaScript în viitor, deoarece standardele web continuă să evolueze cu elemente HTML noi, cum ar fi recentul element <dialog>
.
În al doilea rând, PHP nu este, în mod ironic, foarte bun la modelarea HTML, în ciuda faptului că a fost construit pentru a face exact asta. Sintaxa etichetei sale este prea pronunțată, iar sintaxa șirurilor HEREDOC are suport limitat pentru interpolarea șirurilor.
În cele din urmă, crearea unui punct final în WordPress nu este foarte simplă. Luați în considerare pluginul cărți din exemplele anterioare. Trebuie să avem o cale pe server care să răspundă cu lista de cărți în formă HTML. Cum înregistrăm acest punct final?
- Detectați un parametru GET în timpul acțiunii
init
sauadmin_init
? - Folosiți API-ul Admin Ajax?
- Înregistrați un punct final API REST?
- Adăugați o regulă de rescriere personalizată?
Există multe opțiuni, dar niciuna nu o face atât de simplă pe cât ar trebui să fie.
HATEOAS
Există un detaliu subtil în exemplul nostru anterior care este foarte ușor de ratat și probabil va suna evident odată ce a fost subliniat.
Când primim HTML-ul de pe server, butonul de pe pagină este fie varianta ON, fie varianta OFF. În funcție de care este afișat pe ecran, acțiunea de clic va fi diferită.
Din acest motiv, browserul nu trebuie să înțeleagă aplicația noastră. În mod normal, vom face browserul să înțeleagă dând cod JavaScript pentru a programa în mod explicit în toate comportamentele. Acum, avem doar HTML, iar browserul nu are nevoie de cunoștințe prealabile despre cum se comportă aplicația noastră sau care este starea acesteia. Trebuie doar să redea HTML-ul pe ecran, care în sine codifică starea aplicației noastre.
Acest tip de arhitectură este cunoscut sub numele de HATEOAS, care înseamnă „Hypermedia As The Engine Of Application State”. Este un tip specializat de arhitectură REST care utilizează hypermedia ca mediu pentru transferul de stare, iar aceeași hipermedia devine interfața prin care utilizatorul conduce aplicația în stări noi.
Site-ul web HTMX are o colecție grozavă de articole, eseuri și discuții pe acest subiect, dacă sunteți interesat să aflați mai multe. În acest scop al acestui articol, să trecem la motivul pentru care HTMX ar putea fi o problemă importantă pentru dezvoltatorii WordPress.
HTMX <3 WordPress
WordPress este un server PHP uriaș, monolitic. Pluginurile WordPress sunt, de asemenea, scrise în principal în PHP. Ei pot adăuga noi funcționalități site-ului folosind API-urile PHP furnizate de WordPress, cum ar fi API-ul Hooks și API-ul pentru baze de date. Aceste API-uri nu sunt disponibile din JavaScript, așa că dezvoltatorii de plugin-uri ar trebui să dorească să păstreze cât mai mult din codul lor de plugin pe server. Dacă a existat vreodată o motivație de a utiliza HTMX, aceasta este!
În multe feluri, HTMX a fost creat pentru WordPress. Sau mai degrabă, pentru aplicații precum WordPress; aplicații care preferă să nu fie împovărate cu o limbă străină care îi obligă să-și lase în urmă colecțiile de API-uri de server. Mai ales nu atunci când pur și simplu transferul stării folosind hypermedia ar fi suficient.
Facilitarea creării de interfețe de utilizare bune pentru pluginurile WordPress poate avea un impact dramatic asupra ecosistemului de pluginuri. Dezvoltatorii care întrețin pluginuri gratuite ar putea considera că este mai fezabil să construiască experiențe de utilizator mai bune pentru utilizatorii lor, iar echipele mai mici pot fi capabile să itereze mai rapid funcțiile cu timpul economisit. Acest lucru poate ajuta la creșterea competitivității pluginurilor mai mici pe o piață puternic dominată de echipe mari cu bugete și mai mari.
Pluginurile mai mari pot fi, de asemenea, interesate în mod special. Aplicațiile JavaScript pot crește exponențial rapid. HTMX ar putea permite acestor plugin-uri să-și elimine masivele API-uri JSON și aplicațiile JavaScript și să lase un server HTML slab în locul lor, care are acces deplin la API-urile WordPress.
Gânduri finale
Am fost jucat cu HTMX de ceva vreme, folosindu-l cu PHP și Go. Oferă o alternativă convingătoare pentru construirea de interfețe cu utilizatorul pe web și un argument convingător pentru utilizarea hypermedia pentru a determina starea aplicației.
Dacă sunteți un dezvoltator de pluginuri, asigurați-vă că verificați HTMX. Abia am zgâriat suprafața în acest articol, iar documentația este foarte bine scrisă, cu o mulțime de exemple. De asemenea, este surprinzător de scurt, având în vedere cât de mult HTMX vine din cutie. Ar trebui să puteți începe cu HTMX și PHP în câteva minute.