Всем привет! В данной статье рассмотрим такой javascript модуль как HMPL и как он может заменить HTMX в проекте. Также, рассмотрим в чём их отличия, преимущества и недостатки.
При дальнейшем сравнение двух модулей стоит учесть, что один является языком шаблонов, когда как другой является набором инструментов для работы с HTML, реализуемых через атрибуты и не только.
Начнём с общей концепции для двух модулей.
Концепция сокращения javascript кода путём выноса компонентов пользовательского интерфейса на сервер
Модуль HMPL схож по концепции с HTMX. Мы также можем брать HTML с сервера по API, заменяя тем самым современные фреймворки и библиотеки для создания UI. Возьмём небольшой пример, иллюстрирующий работу HMPL и HTMX, а также такого фреймворка как Vue.js:
Vue.js пример:
createApp({
setup() {
const count = ref(0);
return {
count,
};
},
template: `<div>
<button @click="count++">Click!</button>
<div>Clicks: {{ count }}</div>
</div>`,
}).mount("#app");
Size: 226 bytes (4KB on disk)
HMPL пример:
document.querySelector("#app").append(
hmpl.compile(
`<div>
<button>Click!</button>
<div>Clicks: {{ "src": "/api/clicks", "after": "click:button" }}</div>
</div>`
)().response
);
Size: 206 bytes (4KB on disk)
HTMX пример:
<div>
<button hx-post="/api/increment" hx-target="#counter" hx-swap="outerHTML">Click!</button>
<div id="counter">Clicks: 0</div>
</div>
140 bytes (4 KB on disk)
На примере простого кликера можно увидеть (с небольшими оговорками по данным на стороне сервера и на стороне клиента, а также по html и js разметке, но не в это главная идея), что мы получаем одинаковый интерфейс, хотя размеры файлов на клиенте будут совершенно разными. В этом как раз и основное преимущество подхода создания уже готового, или шаблонного компонента UI на стороне сервера, чтобы пользователь сайта загружал его быстрее с сохранением результата.
Теперь, вспомним, насколько большие приложения сегодня, ну, или по крайней мере раньше (когда server-side rendering не был ещё настолько популярным), могли получаться при использовании фреймворков и библиотек. Тот же SPA (Single Page Application), генерирует весь контент через javascript, когда в html у нас буквально одна строчка, но в том и прикол, что при 10 килобайтном html мы получаем javascript файл размером в несколько десятков мегабайт. Такой сайт, первом заходе, пользователи могут грузить долго.
К примеру, если потенциальный клиент захочет по быстрому заказать себе цветы, то он не будет ждать 10-15 секунд, пока сайт магазина доставки прогрузится, он перейдёт на другой сайт, где сайт будет грузиться быстрее.
Есть ещё много прикладных примеров работы сайтов, которые могут влиять на воронку продаж. Но, суть в том, что главное - это скорость и удобство интерфейса, а вот тут уже есть различия в подходах. Но, лучше сделать это в отдельной статье. Тут же рассматривается сравнение HMPL и HTMX.
Зачем использовать HMPL и в чём его преимущества перед HTMX?
В данном разделе постараюсь рассказать про несколько основных причин, по которым вы можете выбрать, в некоторых случаях, HMPL вместо HTMX:
При схожей идее сокращения кода, два модуля отличаются в понятиях. В случае HTMX, с одной стороны, мы получаем удобный инструментарий работы с уже существующим DOM, но с другой, всё это происходит через HTML и обновляется буквально в режиме реального времени. Мы с большим трудом, через нетипичиные решения, можем работать более ли менее через javascript, а по сути, работа с javascript почти полностью отсутствует. В случае HMPL, с одной стороны, мы без труда можем работать с javascript; генерировать кастомный RequestInit
, создавать тысячи отдельных DOM узлов с той же поддержкой серверного UI, что и на HTMX, но с другой - всё таки работа происходит с кодом, что не всегда удобно, когда хочется создавать проекты быстрее. Возьмём пример кода:
HMPL пример:
import { compile ) from "hmpl-js";
const templateFn = compile(
`<div>
<form onsubmit="function prevent(e){e.preventDefault();};return prevent(event);" id="form">
<div class="form-example">
<label for="name">Enter your email: </label>
<input type="text" name="email" id="email" required />
</div>
<div class="form-example">
<input type="submit" value="Register!" />
</div>
</form>
<p>Email {
{
"src":"/api/register",
"after":"submit:#form",
}
} successfully registered!</p>
</div>`
);
const initFn = (ctx) => {
const event = ctx.request.event;
return {
body: new FormData(event.target, event.submitter),
credentials: "same-origin"
};
};
const obj = templateFn(initFn);
wrapper.appendChild(obj.response);
HTMX пример:
<script src="/path/to/htmx.min.js"></script>
<div>
<form hx-post="/api/register" hx-target="#notification" hx-swap="outerHTML">
<div class="form-row">
<label for="name">Enter your email: </label>
<input type="text" name="email" id="email" required />
</div>
<div class="form-row">
<input type="submit" value="Register!" />
</div>
</form>
<p id="notification"></p>
</div>
На данном примере чётко видно, что HTMX - это больше про максимальное убыстрение и укорачивание кода, когда как HMPL - это нечто комбинированное между HTMX и современным фреймворком или библиотекой для создания UI. Можно сказать, что мы получаем несколько похожий результат, но с учётом того, что мы можем кастомизировать запрос на сервер.
Синтаксис HMPL тоже является в своём роде преимуществом, потому что объекты запроса не привязаны к какому-либо тегу. При рендеринге они заменяются на коментарии, которые не засоряют DOM ненужными тегами. Пример синтаксиса:
HMPL полностью построен на fetch
заросах, которые ввели как стандарт в 2015 году. HTMX для поддержки IE13 по дефолту использует XMLHTTPRequest
, который был введён в 2000 году. Функция fetch позволяет использовать современные возможности javascript в браузерах, такие как AbortController
, signals и другое
И, есть ещё достаточное количество преимуществ, по типу отдельного расширения файла .hmpl при работе с вебпаком и другие, но, на мой взгляд, те, которые я выделил, являются наиболее важными. Вебпак конфиг:
Недостатки HMPL
Также, у hmpl есть ряд недостатков, о которых мне бы хотелось рассказать:
У HMPL пока нету поддержки WebSocket
, что может усложнить внедерение кода в проект. В HTMX данная поддержка присутствует.
Так как происходит использование fetch
, то в некоторых старых версиях браузера вёрстка поддерживаться не будет.
HTMX - это годами протестированная технология, когда как HMPL - это новый модуль.
Вывод
Язык шаблонов HMPL может заменить HTMX в тех случаях, когда требуется гибкая настройка запроса, а также непосредственная работа с узлами через javascript; Если вы, допустим, хотите создать цикл из 1000 одинаковых узлов, и при этом иметь преимущества серверо-ориентированного UI, то он также подойдёт для задачи. Если же цель стоит в полной минимизации работы с javascript, либо же в использовании устоявшегося протестированного модуля и простым подключением к серверу с минимальным количеством HTML кода, то тут HTMX хорош.
Ссылки:
Комментарии (9)
ilya_chch
17.10.2024 09:37Мне кажется, автор не понимает, зачем и как использовать htmx. И примеры некорректны.
Первый пример на vue показывает инкремент на клиенте. Про HMPL не скажу, но htmx подразумевает обновление на бэке. При этом не понятно, зачем
hx-get="/api/clicks"
наdiv
- какое действие должно триггернуть это?
Во втором примере - тоже не верное использование. Опять непонятныйhx-get="/api/registeredEmail"
на span, который так же ничем не будет вызван. Еще иonsubmit="function prevent(e){e.preventDefault();};return prevent(event);" id="form">
зачем-то.Первый пример должен быть примерно таким:
<div> <button hx-post="/api/increment" hx-target="#counter" hx-swap="outerHTML">Click!</button> <div id="counter">Clicks: 0</div> </div>
и в зависимости от ответа бэка на такой запрос может меняться
hx-swap
-outerHTML
, если возвращается<div id="counter">Clicks: {{count}}</div>
, либоinnerHTML
если бэк отвечает простоClicks: {{count}}
Второй пример должен быть таким:
<script src="/path/to/htmx.min.js"></script> <div> <form hx-post="/api/register" hx-target="#notification" hx-swap="outerHTML"> <div class="form-row"> <label for="name">Enter your email: </label> <input type="text" name="email" id="email" required /> </div> <div class="form-row"> <input type="submit" value="Register!" /> </div> </form> <p id="notification"></p> </div>
И бэк должен ответить
<p id="notification">Email {{ email }} successfully registered!</p>
.Смысл HTMX мне видится не в замене реактивных клиентских фреймворков (про сравнение с vue), а упрощение SSR (возврат к концепции, когда все рендерится на бэке), упрощении взаимодействия бэка и фронта и добавлении интерактивности. Понятно, что какой-нибудь draw.io не сделаешь на HTMX, но для какого-нибудь не сильно сложного сайта (тот же хабр) зачем тянуть какой-нибудь frontend framework или библиокету?
antonmak1 Автор
17.10.2024 09:37Поправил примеры с HTMX - спасибо! По поводу того, что не знаю, зачем HTMX использовать, может оно и так. Если работать с сервером, то иногда требуются дополнительные настройки, современные функци, идующие с fetch, и ещё плюшки работы с javascript и DOM деревом. HTMX упрощает в этом смысле работу с сервером, что всего по минимуму, но на практике, когда хочется чего-то большего, то библиотека выдаёт свой потолок вот этими упрощениями.
ilya_chch
17.10.2024 09:37Если работать с сервером, то иногда требуются дополнительные настройки, современные функци, идующие с fetch, и ещё плюшки работы с javascript и DOM деревом
Например?
Я не говорю, что HTMX должен заменить библиотеки и фреймворки. Я считаю, что разные инструменты нужны для разных вещей. Для минимального манипулирования DOM яв предпочитаю использовать hyperscript (от автора HTMX и неплохой интеграции с ним) или alpineJS.
Текущий подход с отдельным бэком и фронтом на React/Vue/Angular/Svelte/etc... позволяет более гибко управлять командами, разделяя ответственность, строя независимые циклы релизов и прочее. Но у этого есть цена - переусложнение (отдельный пайплайн сборки фронта, отдельные настройки для SSR, backend-for-frontend простихоспади), проблема синхронизации и передачи состояний (раньше состояние хранилось и управлялось на бэке). И некоторые функции в текущих фреймворках выглядят как решения проблем, которые были искусственно созданы. Ну и порой неадекватный размер фронтовых бандлов - туда же.
Для того, чтобы отобразить просто список статей/статью, табличку, обработать форму - вовсе не обязательно строить второе приложение.
Это, само собой, не касается приложений, которые полностью работают на фронте (тот же draw.io, google docs, всякие игры и прочее).
Если правильно разбить html на бэке (на переиспользуемые компоненты) - работа с htmx не доставляет головной боли=)При этом, в случае с HMPL - если я правильно понял, это все равно отдельный JS файл (или файлы), который с нуля строит страницу. Концептуально, он выглядит более похожим на фреймворки большой тройки. И получается вообще все будет в бандле, даже элементы страниц, которые на данный момент не нужны. Понятно, что можно как-то настроить бандлер и подгрузку модулей, чтобы грузилось только то, что нужно на текущий момент, но это не просто и выглядит как решение выдуманной проблемы.
В целом, я категорически не согласен с мыслью:
Модуль HMPL схож по концепции с HTMX
toxadx
17.10.2024 09:37Сравнение некорректное, т.к. автор не понимает концепцию HTMX, а рассуждает привычными концепциями.
Для понимания концепции HTMX рекомендую бесплатную книжку - https://hypermedia.systems/book/contents/
alpatovdanila
Можете, пожалуйста, объяснить зачем вообще нужен htmx? Мы все последние 20 лет вешали атрибуты на элементы и обрабатывали их через жс (можно даже было собрать это в 1 файл и сказать что это библиотека), но потом пришло понимание что хтмл просто не очень хорошо подходит для шаблонизации и в целом для описания императивной логики, которая в любом случае всегда нужна в реальной жизни. К тому же в HTMX все равно есть идиоматические способы писать вещи на жс. А для чего это все тогда?
antonmak1 Автор
Для сокращения размеров файлов, скачиваемых на клиенте. От этого всё идёт. Условно, скачать 1 мб HTML и потом 20 мб с css и html с сервера быстрее, чем 21 мб сразу качать.
alpatovdanila
1мб хтмл и потом стили и жс - это же то что происходит сейчас при использовании любого фреймворка. Как раз htmx должен раздувать html потому что теперь в нем дополнительные атрибуты и "код"
antonmak1 Автор
Но, есть много ньюансов с кешированием, клиентскими данными, быстротой разработки и другим. Это просто быстрый ответ на вопрос.