HTMX podría ser un gran problema para WordPress
Publicado: 2024-05-10Crear una experiencia de usuario rica en el navegador puede ser una tarea desafiante, que a menudo requiere una cantidad significativa de código JavaScript. A medida que crecen las necesidades y ambiciones de nuestra aplicación, también crece la complejidad de nuestro código JavaScript. Por lo tanto, no sorprende la frecuencia con la que los desarrolladores han revisado la forma en que pensamos y escribimos las aplicaciones JavaScript.
Días desde el último framework JS.
Los desarrolladores de complementos de WordPress lo tienen peor. El entorno al que nos dirigimos no es un servidor que controlemos nosotros ni uno con control total sobre toda la página. Si bien es muy posible utilizar un marco de JavaScript con éxito en un complemento de WordPress, también puede ser muy fácil terminar con un proyecto cuya escala y complejidad van más allá de lo que pretendías o esperabas.
Pero ¿y si no fuera necesario que fuera así? En este artículo, exploraremos cómo se crean las IU web modernas con JavaScript, las dificultades que enfrentan los desarrolladores y la alternativa que ofrece HTMX. En particular, veremos por qué HTMX y WordPress pueden ser una combinación perfecta.
¿Cómo llegamos aquí?
Antes de JavaScript, los navegadores eran básicamente lectores de documentos glorificados. Como tal, la mayoría de las experiencias en la web fueron "aplicaciones de varias páginas", o AMP para abreviar. Las AMP son aplicaciones web que constan de varios documentos HTML, uno para cada página de la aplicación. A medida que el usuario utiliza la aplicación, se le muestran diferentes documentos con diferentes acciones disponibles.
Las AMP son muy sencillas de construir. La navegación se realiza utilizando etiquetas <a>
para vincular a otros documentos, y la entrada del usuario se puede capturar con un elemento <form>
. El servidor responde a las solicitudes de enlaces y formularios con nuevos documentos HTML, reemplazando la página que se muestra en la pantalla.
Un buen ejemplo de AMP con el que probablemente esté muy familiarizado es WP Admin. Cada página de administración es un documento con HTML generado por el código PHP de WordPress que se ejecuta en el servidor. La mayoría de las páginas de WP Admin, como las páginas de configuración de WordPress, tienden a estar compuestas principalmente por formularios que usted, el usuario, puede enviar.
Por el contrario, una aplicación de una sola página, o SPA, es una aplicación que utiliza una única página HTML. Luego, la navegación y la entrada del usuario se manejan mediante código JavaScript, cambiando dinámicamente partes de la página en el lugar sin necesidad de cambiar toda la página o actualizarla. Esto da como resultado una experiencia de usuario más fluida y con mayor capacidad de respuesta.
Hoy en día, muchas aplicaciones web utilizan SPA para su interfaz web. En RebelCode, hemos creado SPA para las interfaces de administración de nuestros dos complementos principales de WordPress: Spotlight y Aggregator. El editor de sitios relativamente nuevo en WordPress también es un SPA, al igual que el editor de publicaciones basado en bloques.
El precio que pagamos
Los SPA son sus propias aplicaciones, escritas en JavaScript y que se ejecutan en el navegador. Su propia definición es también su mayor advertencia: no tienen acceso inmediato a los recursos del servidor. Esto significa que necesitamos establecer un canal de comunicación entre el SPA y el servidor.
Creemos un complemento de WordPress simple para usar un ejemplo. Este complemento proporciona
una interfaz de usuario CRUD sencilla para gestionar libros. La API interna del complemento en el servidor puede verse así:
<?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;
Para crear nuestra interfaz SPA moderna, usaremos un marco de JavaScript como React; el marco de JavaScript más popular que también utiliza WordPress. Comencemos agregando una página de administración:
<?php add_action('admin_menu', function () { add_menu_page('Books', 'Books', 'manage_options', 'books', 'books_page'); }); function books_page() { echo '<div></div>'; }
Nuestra página representará un único elemento <div>
vacío que servirá como raíz de nuestra aplicación React donde se representará el resto de la interfaz de usuario.
const rootEl = document.getElementById("books-app"); const root = ReactDOM.createRoot(rootEl); root.render(<BooksApp />); function BooksApp() { return ( <div> <h1>My Books</h1> ... </div> ); }
Entonces, ¿cómo enumeramos los libros almacenados en la base de datos? El código para hacerlo está en el servidor, por lo que necesitamos una forma de llamarlo y obtener su resultado.
Para hacer eso, podemos exponer una API JSON desde el servidor. Luego, la aplicación React puede realizar una solicitud en la URL de nuestra API, recibir los libros en formato JSON y luego representar la lista. Para este ejemplo, supongamos que hemos agregado un punto final a la API REST de 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", }, ] }
Luego podemos escribir un componente de React que busque los libros y los represente como una lista:
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> ); }
Pero esta solución es demasiado ingenua y produce una experiencia de usuario difícil. No tiene en cuenta los cambios de estado después de que el componente se desmonta, no almacena en caché la respuesta, no vuelve a intentar consultas fallidas ni evita que el estado obsoleto sobrescriba el estado más reciente. De hecho, generalmente se desaconseja la forma en que usamos fetch()
en un efecto de React.
En muchos sentidos, esto puede ser peor que un AMP tradicional. Entonces, para hacer esto correctamente, necesitaremos implementar algunas cosas más en nuestro cliente. O, de manera más realista, utilice paquetes de terceros.
Pero todo esto está empezando a parecer una cantidad desproporcionada de esfuerzo sólo para presentar una lista de libros. ¿Realmente necesitamos crear una aplicación JavaScript y una API JSON para crear una experiencia de usuario fluida?
Comparemos esto con un MPA, donde la representación de la lista de libros se puede lograr en solo unas pocas líneas de código PHP, sin dependencias:
<?php function render_books() { ?> <ul> <?php foreach (get_books() as $book): ?> <li> <a href="<?= $book->url ?>"> <?= $book->title ?> </a> </li> <?php endforeach; ?> </ul> <?php }
Pero, por supuesto, ésta no es una comparación justa. Esta lista de libros es sólo HTML estático; no reacciona a los cambios de estado ni a la entrada del usuario.
Si queremos tener una experiencia similar a SPA y al mismo tiempo renderizar el HTML en el servidor, donde nuestro código tiene acceso inmediato a la base de datos, necesitaremos encontrar una manera de que el HTML renderizado por el servidor llegue al navegador. y reemplazar la lista anterior de libros. Pero lograr esto sin ningún código JavaScript es actualmente imposible, por lo que tendríamos que hacer el esfuerzo y usar JavaScript de todos modos.
Pero no necesitamos escribirlo nosotros mismos.
Presentamos HTMX
HTMX es una pequeña biblioteca de JavaScript que hace principalmente una cosa: permitir que HTML solicite nuevo HTML del servidor. Lo hace utilizando nuevos atributos, que nos permiten decirle a HTMX de dónde obtener el nuevo HTML, con qué intercambiarlo y qué desencadena el intercambio. Actúa como un puente entre nuestro servidor HTML y la página del navegador.
Esta es una forma muy diferente de pensar en los SPA, ya que no estamos creando una aplicación JavaScript cliente para actualizar la página actual. En su lugar, simplemente agregamos algunos atributos HTML para indicarle a HTMX cómo queremos que cambie la página cuando suceden ciertos eventos.
Incluso sin HTMX, ya puedes cambiar lo que se muestra en la pantalla usando solo HTML, aunque de forma muy limitada. Ya estás familiarizado con esta característica HTML: el humilde elemento de enlace <a>
.
<a href="https://my-wp-site.com/books">View books</a>
Un elemento de enlace proporciona al navegador toda la información necesaria para realizar la navegación. Cuando se hace clic en él, el navegador toma el href
del elemento, realiza una solicitud en esa URL, descarga la respuesta y, suponiendo que contenga HTML, reemplaza el contenido de la página con el nuevo HTML.
El elemento <form>
es otro ejemplo de cómo HTML puede solicitar HTML nuevo.
<form action="/contact.php"> <label> Your message: <input type="text" name="message" /> </label> <button type="submit">Send message</button> </form>
Esta vez, el navegador recopila los valores de todas las entradas del formulario, los envía al servidor, descarga la respuesta y la muestra en la pantalla.
¿Por qué sólo
Del archivo Léame de GitHub de HTMX<a>
y<form>
deberían poder realizar solicitudes HTTP? ¿Por qué sólo debería poder reemplazar toda la pantalla?
Bueno, HTMX cambia eso.
<a href="https://my-wp-site.com/books" hx-target="#books"> View books </a> <div></div>
Con el atributo HTMX hx-target
, al hacer clic en el enlace ahora se colocará la respuesta de https://my-wp-site.com/books
dentro del elemento con el ID de "books"
. Por supuesto, el objetivo aquí no es incrustar una página dentro de otra. Nuestro servidor no necesita responder con la página completa, sino que puede simplemente responder con un fragmento HTML.
Al exponer fragmentos HTML de nuestro servidor y decirle a HTMX cómo, dónde y cuándo obtener esos fragmentos, podemos crear una aplicación web tipo SPA sin ningún JavaScript, donde el servidor tiene el control total. En cierto sentido, HTML se ha convertido en nuestro nuevo JSON.
Y todo lo que tenemos que hacer es cargar el script HTMX en nuestra página:
<script src="https://unpkg.com/[email protected]"></script>
(Asegúrese de consultar la documentación HTMX para obtener instrucciones, ya que el código anterior puede estar desactualizado).
Veamos otro ejemplo:
<button hx-get="/button/off" hx-target="this" hx-swap="outerHTML"> Turn off </button>
Hay mucho más sucediendo aquí, así que analicémoslo:
-
hx-get
especifica la URL a la que enviar una solicitudGET
cuando se hace clic en el botón. -
hx-target="this"
le dice a HTMX que intercambie el botón en el que se hizo clic con la respuesta. -
hx-swap="outerHTML"
le dice a HTMX que cambie todo el botón, no solo lo que hay dentro.
En conjunto, esto le dice a HTMX:
Cuando se hace clic en el botón, envíe una solicitud GET a
/button/off
y reemplace este botón con la respuesta.
Digamos que el servidor responde a /button/off
con el siguiente HTML:
<button hx-get="/button/on" hx-target="this" hx-swap="outerHTML"> Turn on </button>
¿Puedes ver la diferencia? El atributo hx-get
ahora apunta a /button/on
y el texto dentro del botón ahora es "Activar". Cuando se hace clic en este botón, también será reemplazado con la respuesta de /button/on
. Como puedes imaginar, ¡podemos hacer que el servidor responda con el botón original para completar nuestro cambio!
Esta simple idea de permitir que cualquier elemento solicite nuevo HTML del servidor y decida dónde va ese HTML resulta ser bastante poderosa. Podemos crear pestañas, buscar con resultados en vivo, barras de progreso y más.
Pros y contras
A diferencia de la mayoría de los marcos de JavaScript, HTMX no requiere que el código de nuestra aplicación cliente sea compilado ni empaquetado. Esto por sí solo es un gran beneficio; Los sistemas de compilación de JavaScript pueden ser muy difíciles de configurar y mantener, especialmente cuando comienzas a introducir funciones y bibliotecas más exóticas, como preprocesadores TypeScript, JSX, CSS, etc. No es raro que equipos de tamaño mediano a grande tengan uno o más miembros dedicados a esta tarea.
Otro beneficio obvio es la falta de una aplicación cliente independiente. Como todo lo que necesitamos es un servidor HTTP que responda con HTML, podemos usar cualquier lenguaje de programación que queramos. Este puede ser un gran punto de venta para usted si su equipo no está familiarizado con el JavaScript moderno o no es lo suficientemente grande como para justificar la creación de dos aplicaciones. Puede resultar especialmente tentador si eres desarrollador de complementos de WordPress, ya que puedes usar PHP para todos los aspectos de tu complemento.
Pero quizás el beneficio más importante es que ya no necesita una API entre el back-end y el front-end de su aplicación. Esto puede ahorrar una enorme cantidad de tiempo de desarrollo, así como reducir la cantidad de código que puede producir errores, lo que también ahorra tiempo a largo plazo.
Sin embargo, no deberíamos ser tan ingenuos como para suponer que usar HTMX significa no tener que escribir ningún JavaScript. Es posible que aún se requiera cierta cantidad de JavaScript para cosas como arrastrar y soltar, gráficos, selectores de color y fecha, etc. Aunque siempre podemos utilizar soluciones independientes del marco, como SortableJS y UI flotante. Además, es posible que también encontremos menos necesidad de JavaScript en el futuro a medida que los estándares web continúen evolucionando con nuevos elementos HTML, como el reciente elemento <dialog>
.
En segundo lugar, PHP, irónicamente, no es muy bueno creando plantillas HTML, a pesar de haber sido diseñado para hacer precisamente eso. La sintaxis de su etiqueta es demasiado detallada y su sintaxis de cadena HEREDOC tiene un soporte limitado para la interpolación de cadenas.
Por último, crear un punto final en WordPress no es muy sencillo. Considere el complemento de libros de los ejemplos anteriores. Necesitamos tener una ruta en el servidor que responda con la lista de libros en formato HTML. ¿Cómo registramos este punto final?
- ¿Detectar un parámetro GET durante la acción
init
oadmin_init
? - ¿Utiliza la API Admin Ajax?
- ¿Registrar un punto final de API REST?
- ¿Agregar una regla de reescritura personalizada?
Hay muchas opciones, pero ninguna lo hace tan sencillo como debería ser.
ODIAOAS
Hay un detalle sutil en nuestro ejemplo anterior que es muy fácil pasar por alto y probablemente parecerá obvio una vez que se haya señalado.
Cuando obtenemos el HTML del servidor, el botón de la página es la variante ON o la variante OFF. Dependiendo de cuál se muestre en pantalla, la acción de clic será diferente.
Debido a esto, no es necesario que el navegador comprenda nuestra aplicación. Normalmente haríamos que el navegador comprenda dándole código JavaScript para programar explícitamente todos los comportamientos. Ahora sólo tenemos HTML y el navegador no necesita conocimientos previos de cómo se comporta nuestra aplicación ni cuál es su estado. Solo necesita representar el HTML en la pantalla, que a su vez codifica el estado de nuestra aplicación.
Este tipo de arquitectura se conoce como HATEOAS, que significa 'Hypermedia As The Engine Of Application State'. Es un tipo especializado de arquitectura REST que utiliza hipermedia como medio para la transferencia de estado, y ese mismo hipermedia se convierte en la interfaz a través de la cual el usuario lleva la aplicación a nuevos estados.
El sitio web HTMX tiene una gran colección de artículos, ensayos y charlas sobre este tema, si está interesado en obtener más información. Para los fines de este artículo, pasemos a explicar por qué HTMX podría ser tan importante para los desarrolladores de WordPress.
HTML <3 WordPress
WordPress es un servidor PHP monolítico y gigante. Los complementos de WordPress también están escritos principalmente en PHP. Pueden agregar nuevas funciones al sitio utilizando las API de PHP proporcionadas por WordPress, como la API de Hooks y la API de base de datos. Estas API no están disponibles en JavaScript, por lo que los desarrolladores de complementos deberían conservar la mayor cantidad posible de código de complemento en el servidor. Si alguna vez hubo una motivación para usar HTMX, ¡ésta es!
En muchos sentidos, HTMX fue creado para WordPress. O mejor dicho, para aplicaciones como WordPress; aplicaciones que prefieren no verse cargadas con un idioma extranjero que las obligue a dejar atrás sus colecciones de API de servidor. Especialmente no cuando simplemente transferir el estado usando hipermedia sería suficiente.
Facilitar la creación de buenas interfaces de usuario para complementos de WordPress puede tener un impacto dramático en el ecosistema de complementos. A los desarrolladores que mantienen complementos gratuitos les puede resultar más factible crear mejores experiencias de usuario para sus usuarios, y los equipos más pequeños pueden iterar más rápido las funciones con el tiempo ahorrado. Esto puede ayudar a que los complementos más pequeños sean más competitivos en un mercado fuertemente dominado por grandes equipos con presupuestos aún mayores.
Los complementos más grandes también pueden resultar especialmente interesantes. Las aplicaciones de JavaScript pueden crecer exponencialmente rápido. HTMX podría permitir que estos complementos eliminen sus enormes API JSON y aplicaciones JavaScript, y dejen en su lugar un servidor HTML sencillo que tenga acceso completo a las API de WordPress.
Pensamientos finales
He estado jugando con HTMX por un tiempo, usándolo con PHP y Go. Ofrece una alternativa convincente para crear interfaces de usuario en la web y un argumento convincente para utilizar hipermedia para impulsar el estado de las aplicaciones.
Si es desarrollador de complementos, asegúrese de consultar HTMX. Apenas hemos tocado la superficie en este artículo y la documentación está muy bien escrita con muchos ejemplos. También es sorprendentemente corto, considerando la cantidad de HTMX que viene de fábrica. Debería poder comenzar con HTMX y PHP en unos minutos.