Inicio / Artículos / HTMX frente al valor por defecto de las SPA: cuando la hipermedia supera a un framework de JavaScript

HTMX frente al valor por defecto de las SPA: cuando la hipermedia supera a un framework de JavaScript

Cómo los atributos htmx reemplazan la renderización del lado del cliente, qué significan realmente los tamaños de los paquetes, y una guía equilibrada sobre en qué casos ganan las aplicaciones hipermedia y en qué casos sigue siendo superior React.

2260 palabras

Muchos equipos optan por React en cada proyecto nuevo, incluidos paneles de administración y herramientas CRUD que consisten principalmente en formularios y tablas. htmx sostiene que una gran parte de esas aplicaciones nunca necesitó un framework del lado del cliente: el servidor puede enviar HTML, y unos pocos atributos permiten que cualquier elemento obtenga e intercambie fragmentos de él. Esta guía explica cómo funciona htmx, compara su impacto con el de React y detalla tanto las verdaderas ventajas como las limitaciones que sus defensores suelen pasar por alto, para que pueda elegir una arquitectura de forma deliberada en lugar de por costumbre.

Se supone que ya has desarrollado aplicaciones web y que has pasado la mayor parte de tu tiempo con React o un framework similar.

Cómo el SPA se convirtió en la opción por defecto para todo

Alrededor del año 2013, la industria cambió su modelo fundamental. En lugar de que los servidores devolvieran páginas HTML, comenzaron a enviar JSON, y el JavaScript en el navegador convirtía ese JSON en la interfaz.

Para algunos productos, la aplicación de página única representó un verdadero avance. Gmail, Figma y Google Maps almacenan mucha información en el navegador, y sus interacciones deben parecer instantáneas.

El problema es que este modelo se extendió a todo. Un panel de control interno que muestra filas y permite editarlas terminó teniendo la misma arquitectura que una herramienta de diseño. Un sitio de marketing con un único formulario de contacto pasó a utilizar un bundler, un router, una biblioteca de estado y un proceso de hidratación.

Esa configuración por defecto conlleva costos concretos:

  • Dos bases de código, a menudo en dos lenguajes diferentes
  • El modelo de datos definido en ambos lados
  • Una cadena de herramientas de compilación que hay que mantener y actualizar
  • Una necesidad permanente de mantener el estado del cliente sincronizado con el estado del servidor
  • La afirmación principal de htmx es que muchas aplicaciones asumen estos costos sin obtener nada a cambio.

    Qué es htmx

    htmx es una pequeña biblioteca de JavaScript que extiende el HTML con atributos. Con ellos, cualquier elemento puede enviar una solicitud HTTP y colocar la respuesta en algún lugar de la página. Eso es, en esencia, toda la biblioteca.

    Un cuadro de búsqueda en tiempo real ilustra esta idea. El campo de entrada indica qué URL llamar, qué evento activa la llamada y dónde deben ir los resultados:

    <input type="text"
           name="q"
           hx-get="/search"
           hx-trigger="keyup changed delay:300ms"
           hx-target="#results">
    
    <div id="results"></div>
    

    Lea los atributos como una oración: cuando se suelta una tecla y el valor realmente ha cambiado, espere 300 ms, envíe una solicitud GET a /search y coloque lo que regrese dentro de #results. El modificador delay:300ms atenúa las entradas, de modo que una escritura rápida no envíe una solicitud por cada tecla pulsada.

    El servidor no devuelve JSON. Devuelve un fragmento HTML ya preparado:

    <ul>
      <li>First result</li>
      <li>Second result</li>
    </ul>
    

    htmx inserta ese fragmento en el elemento destino. No hay análisis de JSON, ni plantillas del lado del cliente, ni estado del cliente que pueda desviarse del servidor.

    Los atributos que utilizará con más frecuencia

    • hx-get, hx-post, hx-put, hx-delete permiten elegir el método HTTP y la URL.
  • hx-trigger establece el evento que dispara la solicitud, como click, keyup, load, every 2s o revealed (cuando el elemento se desplaza hasta quedar visible).
  • hx-target selecciona el elemento que recibe la respuesta.
  • hx-swap controla cómo se inserta la respuesta: innerHTML, outerHTML, beforeend o delete.
  • hx-indicator hace referencia a un elemento que se muestra mientras la solicitud está en tránsito.
  • hx-confirm pide al usuario que confirme antes de enviarla.
  • Estos se combinan bien. El siguiente fragmento elimina una fila de tabla: el botón envía una solicitud DELETE, se dirige a la tr más cercana que la contiene, reemplaza toda esa fila por la respuesta (que suele estar vacía) y solicita confirmación primero. El modificador swap:1s retrasa el cambio por un segundo, lo que permite un tiempo de transición en CSS para desvanecer la fila y hacer que la acción parezca más ágil:

    <tr>
      <td>Widget</td>
      <td>
        <button hx-delete="/items/42"
                hx-target="closest tr"
                hx-swap="outerHTML swap:1s"
                hx-confirm="Delete this item?">
          Delete
        </button>
      </td>
    </tr>
    

    Observe lo que falta: no hay archivo de JavaScript separado, ni paso de compilación y tampoco estado del lado del cliente. El servidor sigue siendo el responsable de eliminar el elemento y decidir en qué se convertirá la fila.

    Dos arquitecturas uno al lado del otro

    La diferencia se ve más clara como flujo que como comparación de herramientas.

    • Modelo SPA: el servidor envía JSON, el código del cliente lo renderiza y mantiene el estado; el usuario realiza una acción, el cliente actualiza su estado, vuelve a renderizar y envía JSON de vuelta.
    • Modelo hipermedia: el servidor envía HTML, el navegador lo muestra; el usuario realiza una acción, el servidor responde con nuevo HTML y el navegador lo sustituye.

    En el modelo hipermedia existe exactamente una fuente de verdad: el servidor. Esto elimina todo un tipo de errores en los que el cliente cree algo distinto a lo que indica la base de datos, como cachés obsoletos o actualizaciones optimistas que nunca se reconciliaron.

    Carson Gross, creador de htmx, lo presenta como un retorno a lo que originalmente se pretendía con REST. El enfoque de Roy Fielding para REST incluye la restricción HATEOAS (Hypermedia As The Engine Of Application State): el servidor envía representaciones que indican las acciones disponibles a continuación. Una API típica en JSON no hace esto; el cliente debe saber de antemano qué endpoints existen. HTML lo hace de forma nativa, ya que un enlace representa una transición de estado y un formulario, una acción. Si consideras este planteamiento perspicaz o meramente académico, eso es un buen indicador de cómo te sentirás respecto a htmx en general.

    Midiendo el tamaño del paquete y lo que no te dice

    Los tamaños indicados varían, por lo que resulta útil medirlos. En el momento de escribir esto, la versión minificada de htmx pesaba aproximadamente así:

    htmx.min.js:  51,238 bytes raw
                  16,576 bytes gzipped   (16.2 KB)
    

    Las versiones finales de React 19.2.8, el paquete React junto con el cliente DOM, tenían el siguiente tamaño:

    react.production.js:            4,446 bytes gzipped
    react-dom-client.production.js: 94,757 bytes gzipped
    combined:                       98,420 bytes gzipped   (96 KB)
    

    Eso representa una diferencia de unas seis veces, y solo se refiere al tiempo de ejecución de React. Una aplicación real de React incluye un router, una biblioteca de estado, una capa para obtener datos y sus propios componentes, por lo que los paquetes finales suelen alcanzar varios cientos de kilobytes. En contraste, la cifra correspondiente a htmx representa todas las dependencias del lado del cliente. Las cifras exactas cambian con cada versión, así que hay que volver a medir según las versiones que realmente se vayan a distribuir.

    No obstante, hay que tener cuidado con la conclusión. El tamaño del paquete afecta a la primera carga, no a la rapidez con la que se producen las interacciones posteriormente. Con una buena conexión, la diferencia en el tiempo de carga es pequeña, y en visitas repetidas ambos archivos provienen del caché. El argumento más convincente en cuanto al rendimiento es que htmx no tiene fase de hidratación, ese período en el que una página de React generada por servidor parece lista pero ignora los clics hasta que se conectan sus manejadores de eventos.

    Dónde realmente ayuda htmx

    • Un solo lenguaje y una única base de código. Un equipo que trabaja con Go, Python, Ruby o C# puede desarrollar toda la aplicación. La validación se encuentra en un solo lugar y el modelo de datos se define una sola vez.
    • Sin pipeline de compilación. Una única etiqueta script es suficiente. No hay configuración de herramientas de empaquetado, ni node_modules en el frontend, y tampoco hay necesidad de actualizar constantemente las dependencias del mismo.
    • Comportamiento localizado. Lo que hace un elemento está definido directamente en el propio elemento. En lugar de seguir un clic a través de varios archivos y una base de datos, basta con leer el marcado. Este es uno de los argumentos más fuertes a favor, ya que se refiere a la mantenibilidad y no a la velocidad.
    • Estatuto en un solo lugar. No hay caché del cliente que invalidar, ni datos obsoletos, y tampoco es necesario realizar actualizaciones óptimas que luego haya que revertir.
  • Los equipos que trasladan aplicaciones con muchas operaciones CRUD a htmx suelen informar que el código frontend se reduce entre un 40 y un 60 por ciento. Esta cifra circula ampliamente sin una fuente primaria clara, por lo que debe considerarse anecdótica, pero la tendencia es consistente en todos los informes.
  • SEO y accesibilidad de forma predeterminada. El resultado es HTML generado en el servidor, por lo que los rastreadores pueden ver el contenido y las tecnologías de asistencia reciben una marcación semántica real, siempre y cuando se escriba una buena marcación.
  • Dónde falla htmx

    Estos son los puntos que a menudo no se mencionan.

    Interacción rica y continua

    Los editores de tipo arrastrar y soltar, los canvas, las hojas de cálculo y los gráficos interactivos con funciones de pincel y zoom requieren una interacción continua en lugar de solicitudes discretas. En htmx, cada interacción implica un viaje de ida y vuelta al servidor. En el caso de un editor de texto, eso no constituye un compromiso; más bien descarta a htmx para este tipo de aplicaciones.

    Latencia en redes deficientes

    Los defensores señalan que el alojamiento en servidores periféricos ha reducido significativamente los tiempos de ida y vuelta, lo cual es cierto. Sin embargo, un usuario con una conexión móvil rural débil puede tener que esperar unos cientos de milisegundos para realizar una acción que React manejaría localmente en pocos milisegundos. Las aplicaciones htmx funcionan excelente en redes buenas, pero notablemente peor en redes deficientes, lo cual es lo opuesto a como suele presentarse el argumento.

    Sin aplicaciones para móviles o sin funcionamiento offline

    htmx está diseñado únicamente para la web. React Native permite a un equipo compartir conceptos y una cantidad significativa de código con aplicaciones nativas, por lo que si el desarrollo de aplicaciones móviles nativas forma parte de los planes, esto puede superar a cualquier otro factor. El uso sin conexión también está descartado, ya que cada interacción requiere el servidor.

    Estatus complejo del lado del cliente

    Los asistentes de múltiples pasos con campos interdependientes, los formularios con validación en tiempo real entre campos, o las pantallas donde varios componentes deben reaccionar ante un cambio resultan problemáticos. Los equipos suelen añadir Alpine.js o hyperscript, y en ese punto están armando un framework a partir de componentes individuales en lugar de utilizar uno completo.

    Ecosistema reducido y menor reserva de talento

    React cuenta con un componente maduro para casi cualquier widget. Con htmx, o bien creas tu propio selector de fechas o integras uno de JavaScript independiente y gestionas los límites por tu cuenta. La familiaridad también es importante: en el momento de redactar este texto, las encuestas indican que React es utilizado por más del 40 por ciento de los desarrolladores, frente a aproximadamente el 7 por ciento en el caso de htmx, con una relación de descargas en npm de unos 560 a 1. Esto afecta la rapidez con la que los nuevos empleados se vuelven productivos y cuán fácilmente se pueden encontrar soluciones cuando se enfrentan a problemas.

    Leer cuidadosamente las cifras de adopción

    La realidad es más matizada de lo que sugiere cualquiera de los dos bandos.

    • El uso de React no está disminuyendo. Sigue siendo dominante en términos absolutos con una ventaja muy amplia.
  • La satisfacción con React está disminuyendo. Los datos de las encuestas muestran que su uso se mantiene estable mientras aumentan las respuestas de “no volvería a usarlo”. La gente sigue utilizando React, pero lo disfruta menos, lo cual es una señal clara aunque no equivale al abandono total.
  • El crecimiento de htmx es relativo. Superó las 40,000 estrellas en GitHub, sumó aproximadamente 16,800 nuevas en 2024 y lideró la categoría de frontend en JavaScript Rising Stars. Se trata de un crecimiento rápido partiendo de una base pequeña.
  • Resumen claro: React no está siendo reemplazado, pero su posición como la opción por defecto indiscutida se está debilitando. Tenga en cuenta que gran parte del contenido sobre htmx frente a React en línea está escrito para el tráfico de búsqueda, y cifras como el porcentaje de reducción de código o diversos índices de velocidad se repiten sin citar su fuente. Considérelas indicativas y verifique las fuentes actuales antes de citarlas.

    Elegir entre ellos

    Elige htmx cuando:

    • La aplicación se basa fundamentalmente en formularios y listas: paneles de administración, herramientas internas, aplicaciones CRUD, sitios de contenido, tableros que muestran datos en lugar de manipularlos.
    • La fortaleza de tu equipo está en el backend.
    • Deseas una única base de código que cualquier miembro del equipo pueda mantener en unos años.

    Elige React cuando:

    • El navegador realmente almacena un estado significativo, como en editores, herramientas de diseño, colaboración en tiempo real o manipulación intensiva de datos.
    • Necesitas aplicaciones móviles nativas o soporte sin conexión.
    • Dependes de un ecosistema de componentes maduro.

    También existe una tercera opción que a menudo se ignora: utilizar ambos. htmx puede gestionar las pantallas CRUD mientras que React impulsa las dos o tres vistas que realmente lo necesitan. Nada obliga a adoptar una arquitectura única en todo el producto, y combinar htmx con zonas de React es más sencillo que mezclar dos frameworks SPA. Si ya está utilizando htmx, la guía de actualización a htmx 4 explica los cambios en la próxima versión principal.

    Los React Server Components toman prestada parte de la idea de hipermedia al trasladar el proceso de renderizado al servidor. Sin embargo, siguen necesitando el entorno completo de React y un servidor compatible con Node, por lo que no constituyen una opción ligera; en realidad son React obteniendo algunos de los mismos beneficios manteniendo su peso.

    Puntos clave

    • htmx permite que cualquier elemento envíe una solicitud e incorpore HTML generado en el servidor, lo cual mantiene al servidor como la única fuente de verdad y elimina la sincronización del estado del cliente.
    • Su tiempo de ejecución es aproximadamente una sexta parte del de React antes de agregar cualquier código de la aplicación, pero la ventaja práctica radica más en evitar el proceso de hidratación que en reducir el tiempo de carga.
    • Se destaca en aplicaciones CRUD, herramientas internas y sitios de contenido, pero tiene dificultades con interacciones continuas, redes deficientes, uso en dispositivos móviles, funcionamiento sin conexión y estados complejos del cliente.
    • Combinar ambos representa una arquitectura legítima, no un compromiso.

    La pregunta más relevante detrás de este debate es cómo una arquitectura diseñada para Gmail se convirtió en la opción predeterminada para un formulario de seis campos. Nadie tenía completamente razón o error; una herramienta pasó a ser la predeterminada, y las opciones predeterminadas dejan de analizarse. Sea cual sea la opción que elija, incluido React, hágala fruto de una decisión razonada y no de algo heredado.

    Lecturas relacionadas

  • Timeres de cuenta regresiva sin desviaciones en React: De setTimeout a CSS puro — Compare setTimeout, requestAnimationFrame y una técnica de CSS sin JavaScript para cuentas regresivas en React, incluyendo el truco del retraso único que mantiene los dígitos sincronizados.
  • Budgets de rendimiento para JavaScript: Aplicando límites en el bundle en CI — Aprenda por qué JavaScript cuesta mucho más que su tiempo de descarga, cómo definir un presupuesto de rendimiento realista y cómo hacer que webpack rechace las compilaciones que lo excedan.
  • Una sola solicitud Todo, dos arquitecturas: qué elimina htmx de una pila CRUD — Sigue una única solicitud para agregar un elemento a través de una SPA de React y una página htmx para ver qué capas desaparecen, qué asume el servidor y dónde deja de ser viable htmx.