Не знаю, для Вас, но для меня htmx всегда ощущался глотком свежего воздуха в плотной атмосфере битвы тяжеловесных фронтэнд-фреймворков. Простой, минималистичный и элегантный - htmx возвращал разработчиков в эпоху семантического веба, истинного Restful создания динамичных веб-приложений.
Как мы помним, одним из важных обещаний при переходе с версии 1.0 на версию 2.0 была заморозка API, т.е. Карсон Гросс, создатель htmx, гарантировал, что больших изменений больше не будет - никогда. Все изменения и дополнения выносились в расширения.
Несмотря на большой интерес и воодушевление со стороны фронтэнд сообщества (статьи на habr: тут, тут, тут и тут), адаптация htmx затормозилось в последние несколько лет из-за некоторых, скажем так, спорных решений и ригидности API. Однако изменение ситуации было маловероятным, что привело к созданию альтернативных HATEOAS фреймворков разной степени успешности.
И поэтому мне было приятно прочитать, что 1 ноября 2025 года Карсон Гросс признался: «Я говорил, что не будет версии 3. Но ничего не говорил про версию 4». Так с юмором началась история htmx 4.0, получившей подзаголовок The fetch()ening.
Главное изменение - переход с древнего XMLHttpRequest на современный fetch(). А заодно - генеральная уборка под капотом библиотеки, которая стала проще, прозрачнее и чище.
Почему снова мажорная версия
Гросс всегда настаивал, что htmx 2.0 будет стабильной и долговечной. Но, поэкспериментировав с мини-библиотекой fixi.js, которую он сам написал для экспериментирования с новыми фичами, Гросс понял: современные возможности fetch() и async/await открывают путь к радикальному упрощению реализации идей htmx.
А раз уж всё равно ломать совместимость, почему бы не заодно избавиться от накопившихся «исторических особенностей»?
“If we’re going to do fetch(), let’s clean house.”
Так и родилась идея htmx 4.0 - без XHR, без спорных наследований и с гораздо более прозрачной логикой.
Главные изменения
1. Прощай, XMLHttpRequest. Да здравствует fetch()
Главный герой апдейта - замена сетевого слоя. Теперь под капотом htmx работает  fetch(), а не на XMLHttpRequest. Это изменит внутреннюю модель событий, но для обычного разработчика всё будет по-прежнему:
<button hx-post="/vote" hx-target="#result" hx-swap="outerHTML">
  Голосовать
</button>
<div id="result"></div>
Разница в том, что теперь htmx сможет использовать асинхронные стримы (например, для Server-Sent Events), обрабатывать ошибки и отмены запросов в духе современного JS, и при этом остаться без внешних зависимостей.
2. Атрибуты теперь наследуются явно
Карсон признал свою «самую большую ошибку» - скрытое наследование атрибутов. В 4.0 всё станет предельно честным:
<div hx-target:inherited="#output">
  <button hx-post="/up">Like</button>
  <button hx-post="/down">Dislike</button>
</div>
<output id="output">Выберите вариант...</output>
Если не указать :inherited, кнопки не узнают про hx-target. Больше никаких «магических» эффектов как в CSS - только прозрачность и контроль.
3. История без локального кеша
В htmx 2.0 история страниц сохранялась в localStorage, чтобы ускорить переходы. Но на деле DOM-снапшоты часто ломались из-за сторонних скриптов, скрытых состояний и прочей боли.
Теперь - никакого кеша. При возврате в историю библиотека просто сделает сетевой запрос и подгрузит страницу заново.
Просто. Безопасно. Работает.
Для ностальгирующих (и при необходимости обратной совместимости кода) появится расширение, возвращающее старую модель кэша. Но теперь она не по умолчанию.
Новые возможности
Потоковые ответы и SSE
Переход на fetch() дал доступ к Readable Streams. Теперь htmx сможет обрабатывать потоковые ответы - например, чат, обновления в реальном времени или индикацию прогресса.
<div hx-get="/stream" hx-trigger="load" hx-swap="outerHTML">
  Загрузка...
</div>
Содержимое будет обновляться частями, без полного ререндернига страницы.
Morphing Swap в ядре
В 4.0 появится встроенная поддержка «морфинга» DOM - на основе алгоритма idiomorph, разработанного самим Гроссом. Он умнее классического morphdom и может сам решать, какие узлы сохранить при обновлении.
<div id="profile" hx-swap="morphOuter" hx-get="/user/123"></div>
Благодаря этому интерфейсы будут обновляться плавнее, без мерцаний.
Новый <partial> для частичных обновлений
Out-of-band-вставки теперь будут оформлены цивилизованно - через новый тег <partial>:
<partial hx-target="#sidebar" hx-swap="innerHTML">
  <li>Новый пункт меню</li>
</partial>
Эта конструкция полностью совместима с остальной моделью htmx и делает код читаемым.
View Transitions с очередью
Поддержка View Transitions теперь стала умнее - htmx сам выстраивает очередь анимаций, чтобы они не перебивали друг друга.
CSS-анимации тоже остались, но благодаря async-архитектуре они теперь работают стабильнее.
Новая система событий
Асинхронный движок позволяет гарантировать предсказуемый порядок событий. Новая схема именования:
htmx:<phase>:<system>[:<optional-sub-action>]
Например:
htmx:before:request
htmx:after:swap
Теперь всё логично и линейно.
Улучшенный hx-on
Inline-скрипты через hx-on теперь поддерживают await и контекст ctx:
<button hx-post="/like"
        hx-on:htmx:after:swap="await timeout('3s'); ctx.newContent[0].remove()">
  Убрать элемент через 3 секунды
</button>
Лёгкий способ описать небольшое поведение без стороннего фреймворка.
(Хотя Карсон всё ещё рекомендует Alpine.js для «серьёзных» случаев.)
Что остаётся без изменений
Всё остальное. Ваши hx-get, hx-post, hx-swap, hx-boost, hx-trigger и прочие - живы и здоровы. Более того, 2.0 будет поддерживаться вечно. Если всё работает - можно не обновляться.  Но если хочется немного новых фич и чистоты - 4.0 ждёт.
Когда ждать выхода 4.0
Альфа: уже доступна -
htmx@4.0.0-alpha1Основной релиз: первая половина 2026 года
Стабильный релиз (
latest): примерно в 2027-м
Следить за процессом и прогрессом можно здесь.
А пока порадуемся, что такой замечательный проект получил новый импульс! А сам Гросс подшутил, что логично пронумеровать возможную грядущую мажорную версию как 8.0.