Гениальный механизм простоты веб-разработки полностью переходит на Fetch API, native streaming, объединение DOM через Idiomorph и другие изменения.
HTMX уже довольно давно считался завершенным по функциональности. Это успешный проект, который достигает своих амбициозных целей и широко признан, не говоря уже о том, что широко используется в продакшене. Версия HTMX 2.0 считалась последним словом. Создатель обещал, что HTMX 3.0 не будет.
Поэтому, разумеется, разработчики HTMX решили вырвать двигатель и заменить его на новый, основанный на Fetch API JavaScript. Новую версию они назвали HTMX 4.0, чтобы сдержать обещание.
Это увлекательная история об архитектуре и реализации, которая дает нам прекрасное окно во внутренние механизмы фронтенд-индустрии.
Более простая веб-разработка
Когда я попросил комментарий по поводу перепрыгивания через 3.0, Carson Gross из HTMX ответил мне одной фразой:
«Oops.» — Carson Gross, создатель HTMX
Gross — один из моих любимых персонажей индустрии. Легко понять почему. Он создал the Grug Brained Developer, а также HTMX. Первый — это вся жесткая, проверенная временем мудрость опытного разработчика, изложенная голосом пещерного человека, которая нужна молодым grug, чтобы выжить. Второй — физическое воплощение этих идей: библиотека, которая опирается на HTML и REST, возвращая простоту в веб.
Суть HTMX 4.0 в том, что старый транспортный протокол, объект XHR, удаляется и заменяется на современный и универсальный Fetch API.
Это важно сразу в двух смыслах. Во-первых, это был огромный объем работы для команды HMTX. Во-вторых, это большой выигрыш в производительности и DX.
Современный fetch() особенно хорош тем, что умеет потоково передавать ответы. Это означает, что фронтенд может обрабатывать и применять части интерфейса по мере их поступления, а не ждать завершения всего ответа, прежде чем что-либо сделать. Это похоже на то, что делают React Server Components (RSC, недавнее дополнение к React).
В разработке есть определенная влюбленность в новые и хитрые техники. Это понятно, но временами может становиться патологией. Поэтому всегда существовало встречное течение, которое призывает внимательно смотреть на требования и убирать все лишнее, пока не найдется самое простое решение.
HTMX — один из знаменосцев этой контркультуры. В этом духе ветку HTMX 2.0 объявили финальной версией. Она делает то, для чего была создана, и является завершенным и достаточным решением.
Но иногда находится лучший способ делать вещи, и он заслуживает дополнительных инженерных усилий. Это и есть HTMX 4.0.
Нативный streaming
В HTMX 2.x использовался объект XHR, XMLHttpRequest, корнями уходящий в Internet Explorer конца 1990-х. Браузер должен был буферизовать весь ответ, прежде чем можно было выполнить замену. Переход на ReadableStream через Fetch API позволяет HTMX 4.0 обрабатывать и внедрять HTML-фрагменты по мере их поступления.
Это дает святой Грааль streaming UI, но при этом обходится крошечным скриптом размером 14KB. Более того, мы по-прежнему остаемся в лексиконе HTMX, то есть можем использовать любой бэкенд, который умеет выдавать строку. Это выигрыш в производительности, который на самом деле уменьшает объем JavaScript и делает архитектуру проще.
Иными словами, переход на Fetch — это рефакторинг, который должен принести и больше возможностей, и меньшую сложность.
Объединение DOM через Idiomorph
Хотя нативный streaming — это самый фундаментальный новый аспект HTMX 4.0, есть еще одна очень интересная вещь, которую открывает этот рефакторинг.
Идея «morphing» или «diffing» HTML-страниц позволяет очень быстро обновлять страницы без дополнительной сложности во многих сценариях. Чаще всего это связывают с Hotwired. Принцип работы таков: когда приходит страница или фрагмент, алгоритм сравнивает его с текущим содержимым и заменяет только изменения.
HTMX 4.0 по умолчанию включает алгоритм Idiomorph — новый изящный подход к преобразованию одного DOM-дерева в другое. Проект Idiomorph тоже ведет Carson.
В HTMX 2.0 Idiomorph был расширением. В HTMX 4.0 он достается практически бесплатно. Idiomorph, вдохновленный Morphdom из Hotwired, вывел идею сравнения двух HTML-документов и обновления только минимального набора данных на новый уровень. Сам Hotwired тоже принял Idiomorph.
На странице проекта на GitHub есть отличное техническое описание алгоритма вложенного diff по идентификаторам, который использует Idiomorph.
Idiomorph — не прямое следствие перехода на Fetch, а следствие той простоты, которую Fetch принес в кодовую базу. Использование Fetch сделало возможным включить Idiomorph в ядро.
Наследование prop: breaking change
HTMX 4.0 вводит breaking change в наследовании prop. Это изменение не было вызвано переходом на Fetch, а основано на опыте реального использования. Команда решила, что безопаснее и лучше для DX сделать так, чтобы prop в HTMX не наследовались по умолчанию.
В предыдущих версиях такие атрибуты, как hx-target, наследовались неявно. Это приводило к странным случаям, когда дочерние элементы оказывались затронуты, хотя было непонятно, почему. В HTMX 4.0 наследование стало явным. Для указания того, какие дочерние элементы должны наследовать значение, используется модификатор :inherited, например: hx-target:inherited="#div".
Это соответствует принципу locality of behavior, любимому принципу Grug. Больше не нужно искать по шаблонам-родителям, чтобы понять, где именно кнопка должна заменить свой контент.
История hack осталась в истории
В HTMX 2.x был продвинутый механизм истории, который пытался делать снимок локального DOM и сохранять его в localStorage. Это было оптимизацией. Оказалось, что решение хрупкое. В HTMX 4.0 от него отказались в пользу стандартного поведения, то есть перезагрузки страницы.
Обработка ошибок и замена по статусу
Большинству читателей InfoWorld никогда не придется столкнуться с ошибкой 500 или 404. Но для редких случаев, когда сервер возвращает код ошибки (да, это сарказм), новое поведение HTMX 4.0 состоит в том, чтобы подставить контент. Раньше запрос молча завершался ошибкой. Это поможет разработчикам сразу показывать пользователю визуальную обратную связь вместо того, чтобы оставлять его с поломанным или зависшим экраном.
Самая интересная часть этого обновления — новый синтаксис status-specific swapping. Теперь можно задавать разное поведение для разных HTTP-кодов прямо в HTML. Используя синтаксис вроде hx-status:404="#not-found" или hx-status:5xx="#error-notice", можно изящно направлять разные серверные ошибки в разные UI-элементы.
Тег <hx-partial>
Добавление <hx-partial> — крупное структурное улучшение. Оно позволяет оборачивать фрагменты в ответе так, чтобы они могли явно нацеливаться на конкретные элементы, например <hx-partial hx-target="#sidebar">. Это более чистая и читаемая альтернатива старым out-of-band, или OOB, заменам.
Это похоже на Turbo Streams от Hotwired. Таким образом видно, что HTMX и Hotwired взаимно влияют друг на друга с пользой.
Идея в том, что сервер может отправлять набор фрагментов с указанными целями, а затем они помещаются в интерфейс. Это позволяет выполнять сложные многоточечные обновления интерфейса на основе одного серверного ответа.
Нативные view transitions
Вдобавок ко всему, HTMX 4.0 теперь по умолчанию интегрируется с нативным браузерным View Transitions API. Это дает анимированные переходы между состояниями страницы, похожие на поведение приложения, например fade или slide, без дополнительного CSS или JavaScript.
Обход JavaScript-сложности
Даже если вы не знакомы с HTMX, на него стоит посмотреть, чтобы понять, чего именно он пытается достичь. Это важный взгляд на веб-разработку. Наряду с такими проектами, как Hotwired, HTMX показывает, как можно выжать максимум из самых простых стандартных возможностей.
После того как понимаешь этот подход, на всю картину невозможно смотреть совсем по-старому. Даже если вы по-прежнему используете и цените реактивные фронтенды — а я использую.
HTMX задает вопрос: чего мы могли бы добиться с Hypermedia, если бы были очень умны? Ответ: добиться можно очень многого и при этом обойти значительную часть JavaScript-сложности.
Материал — перевод статьи с английского.
Оригинал: HTMX 4.0: Hypermedia finds a new gear
