htmx перевели на fetch() и поменяли наследование атрибутов
Вышел htmx 4.0.0 — после восьми месяцев работы и игры, как скромно уточняет команда. Главные изменения три: атрибуты теперь наследуются только явно через `:inherited`, события переименовали в формат `htmx:phase:action[:sub-action]`, а history больше не использует `localStorage` по умолчанию. Внутри библиотеку переехали с `XMLHttpRequest` на `fetch()`, но для большинства пользователей это должно пройти мимо, как и положено хорошей магии.
Релиз htmx 4.0.0
Команда htmx с огромной радостью объявляет о выходе htmx 4.0.0! Это результат 8 месяцев работы (плюс одна игра), и мы очень довольны результатом.
Идея htmx 4 начала зарождаться, когда я решил создать fixi и в процессе лучше познакомился с API fetch() и асинхронным программированием в JavaScript. (htmx всегда использовал XMLHttpRequest из-за проблем с обратной совместимостью.)
Однажды вечером со мной связался Кристиан, у которого были интересные идеи по стримингу HTML, и это натолкнуло меня на мысль, что переход на fetch() упростит работу как для него, так и для библиотеки в целом. После некоторой работы мне удалось привлечь Майкла и Алекса, и мы начали гонку.
Разработка прошла очень гладко. Мы начали портировать fixi и тестовый набор htmx. Со временем мы заново открыли для себя, почему htmx делал многие вещи именно так, и всё больше приближали новую реализацию к старой. На данный момент поведенческие различия между 2.x и 4.x относительно невелики, а там, где они расходятся, мы сделали осознанный выбор, который, как мы считаем, позволит приложениям на htmx стать 100-летними веб-сервисами.
Обратите внимание: мы не помечаем 4.0 как latest в NPM, потому что не хотим принудительно обновлять пользователей, которые используют неверсионные URL CDN для htmx. Вместо этого 2.x останется latest, а ветка 4.0 останется next до начала 2027 года. Однако на сайте будет использоваться версия 4.0.
Основные изменения
Как уже упоминалось, htmx 4 с точки зрения пользователя почти идентичен htmx 2. Есть три основных изменения:
- Наследование атрибутов теперь по умолчанию явное, а не неявное (это самый большой пункт при обновлении).
- Имена событий htmx были стандартизированы и приведены в порядок. Некоторым опытным пользователям, возможно, придётся изменить события, которые они слушают.
- Поддержка истории теперь по умолчанию не использует
localStorage(что было причиной многих проблем с поддержкой). Большинство людей этого вообще не заметят.
Внутри мы перешли с XMLHttpRequest на fetch(), но для большинства пользователей htmx это должно быть незаметно.
Наследование атрибутов
В htmx 2 многие атрибуты «наследовались» по умолчанию. Это позволяет размещать атрибуты на родительских элементах, и их поведение будет применяться к дочерним элементам. Такое поведение, пришедшее из эпохи intercooler.js, было вдохновлено CSS и, как и следовало ожидать, сработало примерно так же, как CSS: мощно, но иногда сложно для понимания.
В htmx 4 атрибуты не наследуются, если вы явно не укажете это, добавив :inherited после имени атрибута:
<!-- htmx 2 -->
<div hx-confirm="Are you sure?">
<button hx-delete="/item/1">Delete</button>
</div>
<!-- htmx 4 -->
<div hx-confirm:inherited="Are you sure?">
<button hx-delete="/item/1">Delete</button>
</div>
Это будет самой большой нагрузкой при миграции с htmx 2 на htmx 4. Чтобы упростить задачу, мы предоставили инструмент командной строки для поиска мест, которые нужно пометить как наследуемые.
Обратите внимание, что такие атрибуты, как hx-disinherit и подобные, больше не нужны и должны быть удалены.
События
События, запускаемые htmx 2, развивались органически на протяжении всего срока жизни библиотеки и были не особенно хорошо организованы, что затрудняло понимание того, какое именно событие срабатывает в какой момент.
В htmx 4 все события теперь следуют шаблону htmx:phase:action[:sub-action]:
| htmx 2 | htmx 4 |
|---|---|
htmx:beforeRequest |
htmx:before:request |
htmx:afterRequest |
htmx:after:request |
htmx:beforeSwap |
htmx:before:swap |
htmx:afterSwap |
htmx:after:swap |
htmx:configRequest |
htmx:config:request |
Кроме того, были внесены следующие изменения:
- Большинство событий ошибок объединены в
htmx:error. Ответы с ошибками HTTP вызываютhtmx:response:error. - События
htmx:xhr:*удалены. htmx 4 используетfetch(). - События
htmx:validation:*удалены в пользу нативной валидации форм браузера.
Полная таблица приведена в разделе «Что нового в htmx 4».
Инструмент проверки обновлений из командной строки отмечает старые имена событий в атрибутах hx-on и в вашем JavaScript, где может их найти.
История
Поддержка истории всегда была встроена в htmx, позволяя реализовывать действия, учитывающие кнопку «Назад», с помощью простых атрибутов. В htmx 2 для сохранения снимков страниц при восстановлении использовался кеш в localStorage. К сожалению, большой источник проблем заключался в том, что этот снимок мог включать мутации DOM, выполненные сторонними JavaScript-библиотеками. При восстановлении страницы эти мутации оставались, но лежащая в их основе логика JavaScript — нет.
htmx 4 не кеширует страницы в localStorage. При навигации назад htmx повторно запрашивает страницу и вставляет её в <body> или в элемент [hx-history-elt], если он присутствует. Это позволяет сторонним JavaScript-библиотекам «просто работать» в большинстве случаев и, при хорошем кешировании запросов, работает очень быстро.
Если вы предпочитаете локальное кеширование, мы теперь поставляем очень полное расширение hx-history-cache, которое восстанавливает историю из sessionStorage и разработано для хорошей интеграции со скриптовыми решениями, такими как Alpine.js и т.д.
Новые возможности
В htmx 4 есть две большие новые функции, обе из которых нас очень вдохновляют:
Морфинг (Morph Swaps)
Теперь мы поддерживаем морфинг-замены «из коробки» с htmx. Я создал idiomorph и чуть не включил его в htmx 2.x, но решил этого не делать. В htmx 4 Майкл проделал отличную работу по улучшению этого алгоритма и его бесшовной интеграции в htmx.
<hx-partial>
Ещё одна крупная новая функция — тег <hx-partial>. Этот тег похож на внеполосные замены (out-of-band swaps), но гораздо понятнее, когда вы хотите сделать что-то большее, чем просто заменить один элемент новой версией самого себя:
<hx-partial hx-target="#messages" hx-swap="beforeend">
<div>New message</div>
</hx-partial>
<hx-partial hx-target="#count">
<span>5</span>
</hx-partial>
Расширения
Многое из того, что вызывает восторг в htmx 4, связано с расширениями. Переход на fetch() внутри позволил нам переосмыслить, как могут и должны работать расширения, и sparked создание (и воссоздание) многих новых расширений, например:
hx-preload— предзагрузка контента (например, при наведении мыши) для ускорения запросов.hx-download— нативная загрузка файлов на основеfetch().hx-alpine-compat— сглаживает проблемы совместимости между htmx и Alpine.js.hx-history-cache— кеширует историю вsessionStorage, обеспечивает совместимость с Alpine.js.
Кроме того, есть три новых или обновлённых расширения для стриминга HTML:
hx-sse— стриминг черезtext/event-stream.hx-ws— стриминг и отправка через WebSocket.hx-multipart— стриминг черезmultipart/mixed.
Наконец, мы решили, что пришло время попробовать свои силы в создании собственного небольшого фронтенд-скриптового решения, которое тесно интегрируется с htmx. hx-live вдохновлён Alpine.js, jQuery и hyperscript, и делает фронтенд-скриптинг приятным и увлекательным. Он даже поддерживает то, что мы называем DOM-ориентированной, HATEOAS-дружественной реактивностью.
В дистрибутиве появился новый пакет htmax.js, который объединяет htmx с наиболее популярными из этих расширений в одном файле, если вы не хотите думать о том, какие именно выбрать.
Обновление
Полное руководство по обновлению см. в разделе «Что нового в htmx 4».
Как упоминалось ранее, мы предоставляем инструмент обновления, который поможет вам:
$ npx htmx.org@4.0.0 upgrade-check -- ./templates
File extensions: .html, .php, .js, .ts, .jinja, .jinja2, .j2, .erb, .hbs
Use --ext to add more (e.g. --ext .vue --ext .svelte)
Scanning 1 file(s)...
Found 8 issue(s) in 1 of 1 file(s).
templates/index.html:1: [inheritance] hx-headers needs :inherited suffix (descendant on line 3 has hx-delete) (this looks like a CSRF token; without :inherited the header does not reach child elements and the server rejects the request)
templates/index.html:2: [inheritance] hx-target needs :inherited suffix (descendant on line 3 has hx-delete)
templates/index.html:2: [inheritance] hx-confirm needs :inherited suffix (descendant on line 3 has hx-delete)
templates/index.html:3: [renamed-attr] hx-disable -> rename to hx-ignore (hx-disable now means 'disable during request')
templates/index.html:4: [removed-attr] hx-vars is removed -> use hx-vals with js: prefix
templates/index.html:4: [removed-attr] hx-prompt is removed -> load the hx-prompt extension to keep the same syntax
templates/index.html:9: [old-event] old event name "htmx:afterRequest" -> "htmx:after:request"
templates/index.html:9: [old-api] htmx.addClass() is removed -> use element.classList.add()
Мы также предоставляем навык для агента, чтобы помочь с обновлением.
Установка
htmx 4.0 можно установить через менеджер пакетов, указав версию 4.0.0, или подключить через CDN:
<script src="https://unpkg.com/htmx.org@4.0.0/dist/htmx.min.js"></script>
или скачать.
LLM
Нравится вам это или нет, многие люди используют LLM, и мы предоставляем следующие файлы навыков для LLM:
htmx-guidance— основные навыки htmx для разработки с htmx 4.htmx-debugging— диагностика проблем htmx во время разработки.htmx-extension-authoring— написание и отладка расширений htmx 4.htmx-upgrade-from-htmx2— миграция кодовой базы с htmx 2.x на 4.x.
(Оставим в стороне вопрос о том, хорошо или плохо выпускать новую версию библиотеки в эпоху LLM!)
Заключение
Мы надеемся, что вам понравится htmx 4. htmx 2 будет поддерживаться бесконечно долго, так что не чувствуйте давления при обновлении.
Я хотел бы поблагодарить следующих людей за их помощь в этом релизе:
- Michael West — невероятный товарищ по команде и разработчик с «grug-мозгом».
- Christian Tanul — вдохновитель htmx 4, руководитель разработки стриминговых и живых расширений.
- Alex Petros — за то, что удерживал корабль на плаву.
- Stephen Mitchell — гений, стоящий за игрой.
- Stu Kennedy — наш эксперт по WebSocket.
- André Ahlert Jr. — за поддержку IDE и редакторов.
- Dien Hoa Truong — за тестирование ранних версий htmx 4 и помощь в исправлении множества ошибок.
Музыка для обновления
Не было бы обновления htmx без музыки для обновления.