DEV Community

Cover image for htmx 4.0.0 ya está disponible: fetch() reemplaza a XMLHttpRequest
lu1tr0n
lu1tr0n

Posted on Originally published at elsolitario.org

htmx 4.0.0 ya está disponible: fetch() reemplaza a XMLHttpRequest

htmx acaba de confirmar el lanzamiento de la versión 4.0.0 de su librería: la primera reescritura mayor del proyecto desde que existe, con el motor interno migrado de XMLHttpRequest a la API fetch() y la herencia de atributos, antes implícita, ahora declarada a mano con el sufijo :inherited.

El equipo, formado por su creador original junto a Christian, Michael y Alex, tardó ocho meses en terminarlo (con una game jam de por medio) y decidió no marcar la 4.0.0 como latest en npm, para no forzar la actualización de los sitios que cargan htmx desde un CDN sin fijar versión.

TL;DR

  • htmx 4.0.0 se anunció el 28 de agosto de 2026 tras 8 meses de desarrollo (y una game jam de por medio).- El motor interno pasa de XMLHttpRequest a la API fetch(), de forma transparente para la mayoría de usuarios.- La herencia de atributos ahora es explícita: hay que agregar el sufijo :inherited (antes era implícita).- Los eventos se renombran al patrón htmx:fase:accion; por ejemplo htmx:beforeRequest pasa a htmx:before:request.- El historial ya no usa localStorage por defecto: htmx vuelve a pedir la página al navegar hacia atrás.- En npm, 2.x sigue siendo latest; 4.0 queda bajo la etiqueta next hasta comienzos de 2027.- Los eventos htmx:xhr:* y htmx:validation:* se eliminan al migrar a fetch() y validación nativa del navegador.- El equipo liberó una herramienta de línea de comandos para detectar atributos sin :inherited y eventos con nombres viejos.

Qué pasó con htmx 4.0.0

El anuncio se publicó el 28 de agosto de 2026 en el blog oficial del proyecto y marca el cierre de un ciclo de desarrollo que arrancó cuando su creador empezó a trabajar en fixi, una librería minimalista que lo obligó a familiarizarse a fondo con fetch() y la programación asíncrona moderna de JavaScript. htmx, desde su origen como intercooler.js, había usado XMLHttpRequest por razones de compatibilidad hacia atrás.

Un colaborador llamado Christian, interesado en streaming de HTML, terminó de convencer al equipo de mover el motor interno a fetch(). Con Michael y Alex sumados al proyecto, el desarrollo avanzó rápido: partieron de un port de fixi combinado con el test suite histórico de htmx, y a medida que avanzaban redescubrieron por qué htmx 2 tomaba muchas de sus decisiones de diseño originales, así que terminaron acercando la nueva implementación a la anterior en la mayoría de los casos.
htmx 4.0.0 cambia su motor interno de XMLHttpRequest a fetch().

Contexto e historia

htmx 4.0.0 llega con una promesa explícita: mantener a las aplicaciones que lo usan funcionando como "servicios web de 100 años". Es la misma filosofía minimalista que impulsó a htmx 2 desde sus días como intercooler.js, pero ahora aplicada a decisiones concretas sobre qué romper y qué preservar.

Por eso el equipo optó por una estrategia de convivencia poco común: en npm, la etiqueta latest seguirá apuntando a la línea 2.x, mientras que 4.0 se distribuye bajo la etiqueta next hasta comienzos de 2027. Esto evita que los miles de sitios que cargan htmx desde un CDN sin fijar versión numérica se actualicen de golpe a una versión con cambios de comportamiento. El sitio oficial de htmx, sin embargo, ya documenta 4.0 como la versión de referencia.

Detalles técnicos y rendimiento

Herencia de atributos explícita

En htmx 2, muchos atributos se heredaban de forma implícita: si ponías hx-confirm en un div padre, el comportamiento se aplicaba también a los botones hijos. Esa herencia, inspirada en el modelo de cascada de CSS, era poderosa pero difícil de rastrear en aplicaciones grandes.

htmx 4.0.0 invierte esa regla por defecto: ningún atributo se hereda a menos que lo declares explícitamente agregando el sufijo :inherited al nombre del atributo. Es, según el propio anuncio, el cambio que más trabajo de migración exige, y por eso el equipo publicó una herramienta de línea de comandos que recorre tu código y señala dónde hace falta agregar :inherited.


  Eliminar

  Eliminar

Enter fullscreen mode Exit fullscreen mode

Con este cambio también quedan obsoletos atributos como hx-disinherit, pensados justamente para cortar la herencia implícita: en htmx 4 ya no son necesarios y se pueden eliminar del markup.

Eventos estandarizados

htmx 2 fue acumulando nombres de eventos de forma orgánica durante años, sin un criterio único: saber en qué momento exacto se disparaba htmx:beforeRequest frente a htmx:configRequest requería memoria o documentación a mano. htmx 4.0.0 ordena todo bajo un patrón único: htmx:fase:accion[:sub-accion].
Evento en htmx 2Evento en htmx 4Cuándo se disparahtmx:beforeRequesthtmx:before:requestJusto antes de enviar la petición fetch()htmx:afterRequesthtmx:after:requestCuando llega la respuesta del servidorhtmx:beforeSwaphtmx:before:swapAntes de reemplazar contenido en el DOMhtmx:afterSwaphtmx:after:swapDespués de reemplazar contenido en el DOMhtmx:configRequesthtmx:config:requestAl configurar los parámetros de la petición
Además, la mayoría de los eventos de error se consolidan en un solo htmx:error, mientras que las respuestas HTTP con código de error disparan específicamente htmx:response:error. Los eventos htmx:xhr:* desaparecen porque htmx 4 ya no usa XMLHttpRequest, y los htmx:validation:* se eliminan en favor de la validación nativa de formularios del navegador. La misma herramienta de línea de comandos que detecta atributos sin :inherited también marca los nombres de eventos viejos dentro de tus atributos hx-on y tu código JavaScript.

sequenceDiagram
    participant B as "Boton"
    participant H as "htmx runtime"
    participant S as "Servidor"
    B->>H: "click en hx-get"
    H->>S: "fetch GET /saludo"
    Note over H: "dispara htmx:before:request"
    S-->>H: "responde HTML"
    Note over H: "dispara htmx:after:request"
    Note over H: "dispara htmx:before:swap"
    H->>B: "reemplaza el DOM objetivo"
    Note over H: "dispara htmx:after:swap"
Enter fullscreen mode Exit fullscreen mode

El nuevo patrón de eventos sigue el formato fase:acción.

Historial sin localStorage por defecto

El soporte de historial (navegar hacia atrás y adelante con comportamiento consciente de htmx) es una característica presente desde los orígenes del proyecto. En htmx 2, la implementación guardaba una foto de cada página en localStorage para restaurarla al volver atrás. El problema: esa foto podía incluir mutaciones del DOM hechas por librerías de terceros, que quedaban congeladas en el snapshot pero sin la lógica de JavaScript que las sostenía.

htmx 4.0.0 elimina el cache en localStorage. Ahora, al navegar hacia atrás, htmx vuelve a pedir la página al servidor y la intercambia dentro de body, o dentro del elemento marcado con [hx-history-elt] si existe uno. Esto permite que scripts de terceros funcionen sin sobresaltos en la mayoría de los casos y, con un buen cacheo de peticiones HTTP, sigue siendo rápido. Para quien prefiera el cacheo local, el equipo mantiene la extensión hx-history-cache, que restaura el historial desde sessionStorage y está pensada para integrarse con Alpine.js y soluciones de scripting similares.

Cómo probarlo hoy

Probar htmx 4.0.0 hoy mismo no requiere más que cambiar la versión del script. Como el paquete todavía no es latest en npm, hay que pedirlo de forma explícita:


  Saludar

Enter fullscreen mode Exit fullscreen mode

Al hacer click, htmx dispara una petición GET a /saludo usando fetch() por dentro y reemplaza el contenido de #resultado con la respuesta HTML del servidor. Vía npm, en Windows, macOS o Linux, la instalación es la misma: npm install htmx.org@next.

Una vez cargado, podés confirmar qué versión está corriendo desde la consola del navegador con htmx.version, y revisar en el panel de red del navegador que las peticiones que antes aparecían como XHR ahora se listan como fetch.

Impacto y análisis

Para la enorme mayoría de los desarrolladores que usan htmx solo con atributos hx-get, hx-post, hx-target y hx-swap puestos directamente sobre el elemento que dispara la acción, htmx 4.0.0 se comporta igual que htmx 2. El cambio de motor a fetch() es interno y no debería requerir tocar una sola línea de HTML.

💡 Tip: antes de saltar a htmx 4.0.0 en un proyecto grande, corré la herramienta de línea de comandos del equipo: señala cada atributo que necesita el sufijo :inherited y cada evento con nombre viejo dentro de tus hx-on.

El impacto real recae sobre aplicaciones grandes que apoyaban su arquitectura en la herencia implícita de atributos, algo común en dashboards con muchas capas de contenedores compartiendo hx-confirm, hx-indicator o hx-swap. Ahí sí hay trabajo de migración explícito, aunque acotado por la herramienta de línea de comandos.

⚠️ Ojo: si tu aplicación depende de atributos heredados implícitamente (hx-confirm, hx-indicator, hx-swap puestos en un contenedor padre), dejarán de funcionar al pasar a htmx 4.0.0 hasta que agregues :inherited.

La decisión de no marcar 4.0 como latest en npm es, en sí misma, una señal editorial: el equipo de htmx prioriza la estabilidad de los sitios existentes sobre la adopción rápida de la nueva versión, algo poco común en un ecosistema de JavaScript acostumbrado a romper compatibilidad entre versiones menores.

Qué sigue

El plan anunciado es mantener 2.x como latest en npm y 4.0 bajo la etiqueta next hasta algún punto de comienzos de 2027, cuando el equipo evaluará el cambio definitivo. El sitio oficial de htmx, mientras tanto, ya documenta la versión 4.0 como referencia principal.

Entre las novedades que llegan con esta versión, htmx 4.0.0 suma Morph Swaps, un nuevo tipo de intercambio de contenido pensado para actualizar el DOM existente en lugar de reemplazarlo por completo; el anuncio oficial promete más detalle sobre esta y otras funciones nuevas en publicaciones posteriores.

📖 Resumen en Telegram: Ver resumen

Probalo vos: sumá el script de htmx 4.0.0 desde unpkg (unpkg.com/htmx.org@4.0.0) a un HTML de prueba y compará en el panel de red cómo cambian las peticiones frente a tu versión actual de htmx 2.

Preguntas frecuentes

¿htmx 4.0.0 reemplaza a htmx 2 de forma inmediata?

No. En npm, la etiqueta latest sigue apuntando a la línea 2.x; htmx 4.0.0 se distribuye bajo la etiqueta next hasta comienzos de 2027, así que hay que pedirla explícitamente.

¿Tengo que reescribir mis atributos hx-get, hx-post o hx-target?

No, esos atributos funcionan igual. El cambio afecta solo a los atributos que heredabas de forma implícita desde un elemento padre; ahora necesitan el sufijo :inherited.

¿Por qué eliminaron el cacheo de historial en localStorage?

Porque el snapshot guardado podía incluir mutaciones del DOM hechas por scripts de terceros que quedaban congeladas sin su lógica original al restaurar la página. htmx 4.0.0 prefiere re-obtener la página del servidor.

¿Qué pasa con mis listeners de htmx:beforeRequest o htmx:afterSwap?

Hay que renombrarlos según el nuevo patrón: htmx:beforeRequest pasa a htmx:before:request y htmx:afterSwap pasa a htmx:after:swap, entre otros cambios documentados en la nota de la versión.

¿htmx 4.0.0 sigue funcionando con Alpine.js o hyperscript?

Sí. La extensión hx-history-cache, pensada para restaurar historial desde sessionStorage, está diseñada específicamente para integrarse bien con Alpine.js y soluciones de scripting similares.

¿Cómo sé qué versión de htmx tengo cargada?

Desde la consola del navegador, con htmx.version una vez que la librería está cargada en la página.

Referencias

📱 ¿Te gusta este contenido? Únete a nuestro canal de Telegram @programacion donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.

Top comments (0)