- PVSM.RU - https://www.pvsm.ru -
Сегодня пользователи ожидают от веб-приложений плавной работы без перезагрузок страниц. К сожалению, эти ожидания обычно реализуются в виде одностраничных приложений (single-page application, SPA), использующих библиотеки и фреймворки наподобие React и Angular. Эти фреймворки очень специализированы и с ними может быть трудно работать.
Новый подход заключается в том, чтобы вернуть возможность реализации этого UX в руки инженеров, разрабатывавших веб-сайты до возникновения безумия SPA, используя готовые наборы инструментов и знания. HTMX — лучший пример такого подхода из тех, что я видел.
SPA позволяют инженерам создавать отличные веб-приложения, но за это приходится платить свою цену:
React — это библиотека. Она позволяет соединять компоненты друг с другом, но не определяет способы маршрутизации и получения данных. Для сборки целого приложения на React мы рекомендуем фулстек-фреймворк React.
До появления SPA разработчики выбирали удобный им язык и передавали HTML в браузер пользователя в ответ на HTTP-запросы. Это нормально, но обеспечивает низкий уровень интерактивности, а в некоторых случаях создаёт раздражающий UI, особенно из-за того, что при каждом взаимодействии страница полностью перезагружается. Чтобы обойти эту проблему, разработчики обычно добавляли JS по своему вкусу.
Хотя такой подход кому-то кажется устаревшим, именно им вдохновлялись разработчики статьи о REST [3], особенно что касается гипермедиа. Гипермедийный подход к созданию веб-сайтов привёл к невероятному успеху WWW.
Ниже показан ответ от API данных, не гипермедиа.
{
"sort": "12-34-56",
"number": "87654321",
"balance": "123.45"
}
Чтобы сделать эти данные полезными в SPA, клиентский код должен понимать структуру и решить, что рендерить, и какие элементы управления сделать доступными.
REST описывает использование гипермедиа. Гипермедиа — это когда твои ответы не просто являются сырыми данными, а полезной нагрузкой, описывающей медиа (вспомните тэги HTML наподобие <p>
, заголовки и так далее) и способ манипуляций с ними (например, form
, input
).
Пример гипермедиа — это сервер, возвращающий HTML с описанием банковского счёта с какими-нибудь видами элементов управления для работы с ресурсом. Теперь сервер отвечает за описание способа рендеринга данных (с небольшим вмешательством CSS) и того, какие элементы управления должны отображаться.
<dl>
<dt>Sort</dt><dd>12-34-56</dd>
<dt>Number</dt><dd>87654321</dd>
<dt>Balance</dt><dd>£123.45</dd>
</dl>
<form method="POST" action="/transfer-funds">
<label>Amount <input type="text" /></label>
<!-- etc -->
<input type="submit" value="Do transfer" />
</form>
Такой подход означает, что у нас есть один универсальный клиент — веб-браузер; он понимает, как отображать гипермедиа-ответы и позволяет пользователю работать с «элементами управления» для выполнения нужных действий.
Карсон Гросс в подкасте Go Time [4]:
… когда только появились браузеры, идея одного универсального сетевого клиента, общающегося с любым приложением через эту безумную технологию гипермедиа, была абсолютно новаторской. Такой она и остаётся.
Если бы вы сказали кому-нибудь в 1980 году «знаешь, ты сможешь использовать одно и то же приложение для доступа к новостям, банковскому счёту, календарю, штуке под названием „электронная почта“ и многому другому», то на тебя бы посмотрели искоса и не поняли, о чём ты говоришь, если собеседник не был членом одной из мелких исследовательских групп, изучавших подобные вещи.
До появления World Wide Web, до веб-браузеров превалирующими паттернами приложений были уникальные и часто «толстые» клиенты.
Хотя создающие SPA люди говорят об использовании «RESTful» API для реализации обмена данными в их коде на стороне клиента, в своей чистейшей форме такой подход не является RESTful, потому что в нём не применяется гипермедиа.
Вместо одного универсального клиента куча разработчиков создаёт уникальные клиенты, которые должны понимать, какие сырые данные они получают от веб-серверов, а затем рендерить элементы управления согласно этим данным. При таком подходе браузер больше походит на среду исполнения JavaScript, HTML и CSS.
Толстый клиент по определению требует больше усилий и затрат, чем тонкий. Однако «первоначальный» подход с гипермедиа недостаточно хорош для всех современных нужд; элементы управления, с которыми может работать браузер, и то, что он требует полного обновления страницы для их использования, делают такой UX неудобным для многих типов веб-приложений.
В отличие от SPA, HTMX не отказывается от архитектурного подхода REST; он дополняет браузер, расширяя его гипермедиа-возможности и упрощая реализацию функционального клиента без особо большого объёма JavaScript, а то и совсем без него.
Для передачи HTML можно использовать любой язык программирования, как мы и привыкли. Это значит, что мы можем использовать проверенный временем надёжный инструментарий с «истинным подходом RESTful», что существенно упрощает разработку и снижает сложность.
HTMX позволяет проектировать страницы, получающие с сервера фрагменты HTML для обновления страницы пользователя и без необходимости перезагрузки всей страницы.
Мы можем рассмотреть это на практике при помощи примера с классическим приложением TODO.
Во-первых, не стоит волноваться о том, что приложение пишется на Clojure. Я выбрал Clojure ради интереса, но красота такого подхода в том, что можно использовать любой подходящий вам язык, если он отвечает на HTTP-запросы отправкой гипермедиа.
Здесь нет ничего особенного, но приложение ощущается как SPA. Нет никаких полных перезагрузок страницы, всё работает очень плавно, как во всех демо SPA, которые вы могли видеть.
Разница заключается в следующем:
Я создал веб-сервер, отвечающий на HTTP-запросы отправкой гипермедиа.
HTMX добавляет возможность задания расширенного гипермедиа, позволяя аннотировать любой HTML-элемент, чтобы просить браузер делать HTTP-запросы для получения фрагментов HTML, которые помещаются на страницу.
Самая удивительная и впечатляющая часть этого демо — функция редактирования. Поле ввода появляется мгновенно, пользователь может отредактировать и страница сразу же обновится. Кажется, как будто для этого требуется много ванильного JS или подход в стиле React, но ниже вы увидите, что всё до абсурда просто.
Давайте начнём с изучения разметки элемента TODO. Ради понятности я вырезал всю разметку, не относящуюся к редактированию.
<li hx-target="closest li">
<form action="/todos/2a5e549c-c07e-4ed5-b7d4-731318987e05"
method="GET">
<button
hx-get="/todos/2a5e549c-c07e-4ed5-b7d4-731318987e05"
hx-swap="outerHTML">
</button>
</form>
</li>
Возможно, вам покажется, что тут много кода, но на самом деле в первую очередь нужно сосредоточиться на понимании функции редактирования:
hx-target
тега <li>
говорит браузеру: «Когда ты получишь фрагмент для рендеринга, я хочу, чтобы ты заменил этот элемент». Дочерние элементы наследуют этот атрибут, поэтому для любых действий HTMX внутри этого тега <li>
возвращаемый HTML
будет заменять содержимое <li>
.hx-get
на кнопке редактирования означает, что при нажатии на неё HTMX
прикажет браузеру выполнить HTTP GET
к URL
и получить новую разметку для рендеринга в <li>
вместо того, что там находится.Когда начинаешь работать с HTMX, проще всего разобраться в происходящем, изучив вкладку Network в инструментах разработчика в браузере.
Когда пользователь нажимает на кнопку редактирования, браузер выполняет HTTP GET
к указанному ресурсу todo. Сервер возвращает гипермедиа-ответ, который является описанием этого ресурса с элементами управления гипермедиа.
<form action="/todos/45850279-bf54-4e2e-a95c-c8c25866a744/edit"
hx-patch="/todos/45850279-bf54-4e2e-a95c-c8c25866a744"
hx-swap="outerHTML" method="POST">
<input name="done" type="hidden" value="false"/>
<input name="name" type="text" value="Learn Rust"/>
<input type="submit"/>
</form>
Затем HTMX берёт этот HTML и заменяет им то, что мы определили как hx-target
. Поэтому пользователь теперь видит эти элементы управления гипермедиа, позволяющие ему манипулировать ресурсом, а не строку, которую мы видели на изображении выше.
Можно заметить, что форма имеет атрибут hx-patch
, то есть при её отправке браузер отправит PATCH
с данными для обновления ресурса. Затем сервер отвечает обновлённым элементом для рендеринга.
В HTMX есть гораздо больше всего, но это сама суть подхода, который полностью идентичен подходу, который использовался на веб-сайтах до того, как стали популярны SPA.
URL
Всё, что делает HTMX — это позволяет браузеру лучше справляться с гипермедиа, давая нам больше вариантов того, что может привести к исполнению HTTP-запроса и позволяя нам обновлять часть страницы, а не перезагружать её полностью.
Благодаря использованию гипермедиа и тому, что мы не относимся к браузеру просто как к среде исполнения JavaScript, мы получаем множество упрощающих жизнь преимуществ:
Последний пункт критически важен для меня и моего работодателя. Я работаю в компании, создающей продукты, используемые по всему миру, и наш контент и инструменты должны подходить для максимального количества людей. Мы не можем ограничивать возможности людей неудачными техническими решениями.
Именно поэтому мы пользуемся progressive enhancement [6].
Progressive enhancement — это философия проектирования, предоставляющая обязательные контент и функциональность максимально возможному количеству пользователей, а максимальную функциональность давая только тем пользователям, которые используют современные браузеры, способные выполнять весь нужный код.
Все функции приложения TODO (поиск, добавление, редактирование, удаление, пометка пункта как завершённого) работают с отключенным JavaScript. HTMX не делает всего этого «бесплатно», усилия разработчиков всё равно требуются, но благодаря такому подходу задачи решаются гораздо проще. Чтобы написать приложение, мне понадобилось около часа, и при этом не потребовалось существенных изменений.
Когда браузер отправляет запрос, заданный HTMX, он добавляет заголовок HX-Request: true
; для сервера это означает, что мы можем отправлять разные ответы; это во многом похоже на content negotiation [7].
Стандартная структура для обработчика выглядит примерно так:
parseAndValidateRequest()
myBusinessLogic()
если запрос в htmx то
вернуть фрагмент гипермедиа
иначе
вернуть полную страницу
конец
Вот конкретный пример HTTP-обработчика для работы с новым TODO:
(defn handle-new-todo [get-todos, add-todo]
(fn [req] (let [new-todo (-> req :params :todo-name)]
(add-todo new-todo)
(htmx-or-vanilla req
(view/todos-fragment (get-todos))
(redirect "/todos")))))
Третья строка «бизнес-логики» вызывает функцию для добавления нового TODO в наш список.
Четвёртая строка — это некий код для определения того, с каким типом запроса мы имеем дело, а последующие строки или рендерят фрагмент для возврата, или перенаправляют на страницу.
По моему опыту разработки гипермедия-приложений с HTMX, такой паттерн встречается очень часто. По самой природе такой архитектуры, если мы можем поддерживать обновление части страницы, то возвращаем фрагмент; в противном случае браузер обязан выполнить полное обновление страницы, то есть или выполнить перенаправление, или просто вернуть весь HTML целиком.
Шаблонизация HTML на сервере — это невероятно развитая область. Существует множество вариантов и превосходных руководств по тому, как структурировать и добавлять для них автоматизированные тесты. Важно то, что все они предоставляют возможности композитинга, поэтому можно чрезвычайно просто вернуть фрагмент или целую страницу.
Конечно, я не могу предсказать будущее, но я считаю, что HTMX (или нечто подобное) в ближайшем будущем станет всё более популярным подходом к созданию веб-приложений.
Недавно было заявлено о том, что HTMX стал одним из двадцати проектов в GitHub Accelerator [8].
Изучение React само по себе является целой отраслью знаний. Он быстро развивается и меняется, и нужно многому учиться. Я симпатизирую разработчикам, которые когда-то делали полнофункциональные приложения и которых современная фронтенд-разработка заставила стать «бэкенд»-разработчиками.
Я создавал на React довольно сложные системы, и хотя в чём-то это было довольно интересно, объём необходимых знаний для большинства приложений несопоставим. У React есть своя ниша, но для многих веб-приложений он чрезмерно мощен.
Подход с гипермедиа на основе HTMX несложно понять, особенно если ты знаком с фундаментом REST (который у «бэкенд»-разработчиков должен быть). Он позволяет создавать функциональные веб-сайты более широкой аудитории разработчиков, не желающих изучать работу с фреймворком и постоянно гнаться за его постоянно меняющейся структурой.
Даже спустя более десятка лет после появления React он не кажется устоявшимся и зрелым. Несколько лет назад хуки стали новинкой, которой должен был научиться каждый и переписать на них все компоненты. А в последние полгода в моей ленте Twitter куча споров и туториалов о новых "RSC" — react server component. Неописуемое удовольствие.
Работа с HTMX позволила мне использовать то, что я изучил 15-20 лет назад и что до сих пор работает, как мой сайт [9]. Этот подход понятен и хорошо задокументирован, а накопленный опыт не зависит от языков программирования и фреймворков.
Я без малейших проблем создал пример приложения на Go и на Clojure, а ведь в Clojure я совершенный новичок. Как только вы разберётесь с основным синтаксисом языка и узнаете, как отвечать на HTTP-запросы отправкой гипермедиа, то сможете приступить к работе; и можно использовать рекомендации по архитектуре и дизайну без необходимости снова и снова изучать новые подходы.
Какой объём навыков вам удастся перенести из React на работу с Angular? Легко ли перейти с одного фреймворка react на другой? Что вы подумаете, когда классовые компоненты станут «плохими» и от вас потребуют использовать вместо них хуки?
Он просто требует меньше усилий!
Hotwire [10] — это библиотека, имеющая схожие с HTMX цели, развитием которой занимается сообщество Ruby on Rails. DHH твитнул [11] следующее.
Hotwiring Rails выражает желание подарить одинокому фулстек-разработчику все инструменты, которые необходимы ему для создания нового Basecamp, GitHub или Shopify. Того, что может создать команда из десятков или сотен людей при наличии миллионов долларов венчурного капитала. Технологии Возрождения для людей эпохи Возрождения.
Поэтому так печально слышать, когда «фулстек» считают уничижительным термином или невыполнимой миссией. Считается, что для создания крутых проектов мы ДОЛЖНЫ быть разрозненным коллективом из фронтенда, бэкенда, сервисов и любых других групп специалистов. А это совершенно не так.
Без когнитивной перегрузки обучения огромному фреймворку из мира SPA и сложностей создания толстого клиента вполне можно создавать функциональные веб-приложения усилиями гораздо меньшего количества разработчиков.
Как говорилось ранее, при использовании подхода с гипермедиа создавать веб-приложения, работающие без JavaScript, достаточно просто.
Важно помнить, что браузер находится в ненадёжном окружении, поэтому при создании SPA необходимо обеспечивать невероятный уровень защиты. Приходится реализовывать большую часть бизнес-логики на стороне клиента; но из-за архитектуры ту же самую логику необходимо воссоздать и на сервере.
Допустим, нам нужно правило, гласящее, что после того, как список помечен выполненным, его нельзя было редактировать. В мире SPA мы бы взяли сырой JSON и вынуждены были создавать бизнес-логику, определяющую, нужно ли рендерить кнопку редактирования в клиентском коде. Однако, если бы мы хотели, чтобы пользователь каким-то образом не обошёл это правило, ту же защиту нужно было реализовать на сервере. Это кажется несерьёзным и простым, но повышает сложность, а вероятность несогласованности повышается.
При подходе с гипермедиа браузер «туп» и ему не нужно об этом волноваться. Разработчик может реализовать это правило в одном месте — на сервере.
Сложность SPA привела к созданию больших отделов бэкенда и фронтенда, что привносит дополнительные затраты.
Типичное разделение команды на фронтенд и бэкенд приводит к большой неэффективности командной работы из-за передачи ответственности и недопонимания, что усложняет выполнение работы. Многие ошибочно считают самой критически важной метрикой личную эффективность, используя её как оправдание такому разделению. Они видят, как сливаются вместе множество PR, и прикладывается много усилий, но игнорируют затраты на координацию.
Например, предположим, что вам нужно добавить на страницу новый элемент данных или новую кнопку. Для многих команд это значит необходимость проведения совещаний по согласованию нового API, создание заглушек для команды фронтенда и координирование релизов.
При подходе с гипермедиа эта сложность полностью отсутствует. Если вам нужно добавить на страницу кнопку, координировать усилия не нужно. Не требуется сильно беспокоиться о структуре API. Вы можете менять разметку и контент так, как вам это нужно.
Команды, обменивающиеся данными в JSON, могут быть крайне неустойчивыми без поддержки и всегда требуют затрат на координацию. Вам могут помочь такие инструменты, как consumer-driven contract, но это всего лишь ещё один инструмент, ещё один аспект, в котором нужно разбираться, и ещё один элемент, который может сломаться. При использовании гипермедиа лишняя трата ресурсов, поддержка и сложность управления версиями API по природе своей не является проблемой; вы можете менять разметку, как вам нужно.
При этом я не хочу сказать, что при таком подходе нет места для разделения ролей. Я работал в командах, где разработчики создавали веб-приложение «от и до», но при этом у нас были люди, специализирующиеся на семантической, доступной разметке, помогавшие нам обеспечивать хорошее качество результата. Невероятно удобно, когда для создания веб-сайта вам не приходится обсуждать API и передавать задачи.
Рендеринг HTML на сервере — это хорошо исследованный путь. В любом популярном языке программирования и в большинстве нишевых существует множество проверенных практикой и совершенных инструментов и библиотек для генерации HTML на сервере.
Я призываю разработчиков, стремящихся к снижению затрат и сложности разработки веб-приложений, попробовать HTMX. Если вы отказывались от создания веб-сайтов из-за справедливого мнения о сложности фронтенд-разработки, то HTMX может стать для вас отличным вариантом.
Я не заявляю, что SPA стали излишними; в них по-прежнему существует реальная потребность, когда требуются очень сложные и быстрые взаимодействия, когда требования к проекту не позволяют тратить время на обращение к серверу для получения разметки.
В 2018 году я заявил [12], что большое количество веб-приложений можно написать с гораздо более простым технологическим подходом, чем SPA. Теперь благодаря технологиям наподобие HTMX моё заявление имеет ещё больший вес. В мире фронтенда разработчики постоянно ждут, что новый фреймворк решит проблемы предыдущего фреймворка, который они используют. Подход с SPA по природе своей более сложен, чем подход с гипермедиа и если наслоение ещё большего количества технологий не может решить проблему, то попробуйте гипермедиа.
Дополнительную информацию можно изучить по ссылкам ниже.
Автор:
ru_vds
Источник [19]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/384908
Ссылки в тексте:
[1] даже рекомендуют использовать поверх их технологии фреймворк: https://react.dev
[2] Remix: https://remix.run
[3] статьи о REST: http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm
[4] Карсон Гросс в подкасте Go Time: https://changelog.com/gotime/266
[5] ClojureScript: https://clojurescript.org
[6] progressive enhancement: https://developer.mozilla.org/en-US/docs/Glossary/Progressive_Enhancement
[7] content negotiation: https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation
[8] HTMX стал одним из двадцати проектов в GitHub Accelerator: https://github.blog/2023-04-12-github-accelerator-our-first-cohort-and-whats-next/
[9] как мой сайт: https://quii.dev/How_my_website_works
[10] Hotwire: https://hotwired.dev
[11] твитнул: https://twitter.com/dhh/status/1341758748717510659
[12] заявил: https://quii.dev/The_Web_I_Want
[13] бесплатную книгу с описанием гипермедиа: https://hypermedia.systems
[14] HTMX: https://htmx.org
[15] Версия на Go: https://github.com/quii/todo
[16] версией на Clojure: https://github.com/ndchorley/todo
[17] DHH о Hotwire: https://world.hey.com/dhh/the-time-is-right-for-hotwire-ecdb9b33
[18] Image: http://ruvds.com/ru-rub?utm_source=habr&utm_medium=article&utm_campaign=perevod&utm_content=rendering_na_servere_i_htmx_eto_budushhee
[19] Источник: https://habr.com/ru/companies/ruvds/articles/736754/?utm_source=habrahabr&utm_medium=rss&utm_campaign=736754
Нажмите здесь для печати.