Что такое htmx и когда JS-фреймворк не нужен
Основы3 минРедакция Innovialabs
Коротко
htmx — небольшая библиотека, которая позволяет обновлять части страницы HTML-фрагментами с сервера через атрибуты; для форм, поиска, таблиц и админок она часто заменяет React или Vue, но не подходит для насыщенных клиентских интерфейсов.
Короткий ответ
htmx — это небольшая JavaScript-библиотека, которая расширяет HTML атрибутами вроде hx-get и hx-post. Любой элемент может отправить запрос на сервер, а ответ — готовый HTML-фрагмент — вставляется в нужное место страницы.
Вместо схемы «сервер отдаёт JSON, клиент рендерит интерфейс» работает схема «сервер отдаёт HTML, браузер его вставляет». Это и называют hypermedia-driven подходом: состояние и логика остаются на сервере, клиентского кода почти нет.
JS-фреймворк не нужен, если интерфейс в основном состоит из форм, списков, таблиц, фильтров и карточек, а данные всё равно живут на сервере.
Как это работает
Ключевые атрибуты:
hx-get,hx-post,hx-put,hx-delete— какой запрос отправить;hx-trigger— по какому событию (клик, ввод, прокрутка);hx-target— куда вставить ответ;hx-swap— как вставить: заменить содержимое, весь элемент, добавить в конец;hx-indicator— что показать во время загрузки.
Бэкенд может быть любым: Django, Laravel, Rails, Go, Node.js, ASP.NET. Он просто рендерит шаблоны, как в классическом сайте, только иногда — не целую страницу, а её кусок.
Типовые сценарии
Форма без перезагрузки
<form hx-post="/contacts" hx-target="this" hx-swap="outerHTML">
<input name="email" type="email" required>
<button>Отправить</button>
</form>
Сервер проверяет данные и возвращает либо форму с ошибками, либо сообщение об успехе. Валидация живёт в одном месте — на сервере.
Живой поиск
<input type="search" name="q"
hx-get="/search"
hx-trigger="input changed delay:300ms"
hx-target="#results">
<div id="results"></div>
Запрос уходит через паузу после ввода, а сервер присылает готовый список результатов.
Пагинация и бесконечная прокрутка
<tr hx-get="/orders?page=2"
hx-trigger="revealed"
hx-swap="afterend">
<td>Загрузка...</td>
</tr>
Когда строка появляется на экране, подгружается следующая порция. Для обычной пагинации достаточно hx-get на кнопке «Ещё» и hx-push-url, чтобы адрес в браузере обновлялся.
htmx против SPA-фреймворков
| Критерий | htmx | React / Vue (SPA) |
|---|---|---|
| Где состояние | на сервере | в основном на клиенте |
| Формат ответа | HTML | обычно JSON |
| Объём клиентского кода | минимальный | значительный |
| Сборка фронтенда | не обязательна | нужна |
| Офлайн-режим | практически нет | возможен |
| Сложные редакторы, drag-and-drop | неудобно | естественно |
| Мгновенная реакция без сервера | нет | да |
| Нужна отдельная фронтенд-команда | обычно нет | обычно да |
Когда htmx — хороший выбор
- админки, CRM, внутренние системы с таблицами и формами;
- проект уже на серверном фреймворке с шаблонами;
- небольшая команда, которой не хочется поддерживать два приложения — API и SPA;
- нужно «оживить» существующий многостраничный сайт без переписывания.
Где начинаются ограничения
- Насыщенный клиентский интерфейс: графические редакторы, канбан с перетаскиванием, сложные дашборды с локальным состоянием.
- Офлайн и нестабильная сеть: каждое действие требует ответа сервера.
- Мобильное приложение и сторонние клиенты: им всё равно нужен JSON API, и его придётся делать отдельно.
- Мелкая клиентская логика вроде открытия меню — для неё рядом с htmx обычно добавляют лёгкую библиотеку, например Alpine.js, или пару строк обычного JavaScript.
Типичные ошибки
- Пытаться повторить SPA на htmx: хранить сложное состояние в DOM и связывать десятки атрибутов.
- Возвращать с сервера всю страницу вместо фрагмента — медленно и ломает вёрстку.
- Забывать про безопасность: шаблоны должны экранировать пользовательский ввод, а POST-запросы — защищаться от CSRF.