Впечатления от знакомства с микрофреймворком AlpineJS
В этом месяце я умудрился познакомиться в работе с двумя полезными для меня инструментами веб-разработки, неплохо отдохнуть в Удмуртии, съездив с супругой в прекрасный город Ижевск, а также посетив рок-фестиваль «Улетай». Удивительно, но даже на огромном рок-фестивале я с легкостью узнавал типичных программистов. Например Java-разработчиков я легко узнал по флагу с названием языка и типичным логотипом в виде чашки кофе, видел PHP-разработчиков в футболке PHP с логотипом в виде слона, а также встретил разработчиков из Tilda (узнал их по фирменной футболке).
Но я немного отвлекся от темы статьи. Как уже упоминал, я для себя открыл два новых инструмента, которые неплохо себя показали в работе — AlpineJS и HTMX, но в статье я решил уделить внимание пока только AlpineJS, поскольку про HTMX я хочу написать позднее, после того как чуть побольше с ним поработаю.
Проблема использования React/Vue/Angular в случае простейших рутинных задач с DOM
Реактивный подход очень удобен при решении рутинных задач при работе с DOM-моделью. Для реализации реактивности на ум сразу приходят React/Vue/Angular. Но проблема в том, что каждый из этих замечательных инструментов работает в своей экосистеме, со своим синтаксисом шаблонов, виртуальным DOM и зависит от кучи сторонних инструментов (например систем сборки). Такая ситуация отлично подходит для реализации сложных и самодостаточных веб-приложений. Но при этом эти инструменты иногда заметно избыточны, например при необходимости простой работы с DOM в уже сверстанном сайте, при этом избежав конфликтов со сторонними скриптами. Или сделать форму отправки заявки более интерактивной и с т.з. кода более наглядной, без кучи всяких addEventListener-ов и непонятной логики.
Ранее я при верстке сайта, в основном брал Vue c его замечательным компонентным подходом. И впринципе все было неплохо, кроме разве что того, что верстка очень сильно зависела от системы сборки (vite, webpack и пр.), что не очень удобно при создании шаблона сайта. Верстка состояла из кучи Vue компонентов, которые собирались в готовую верстку. Тут появляется сложность в том, что когда верстка уже натянута на CMS, вносить правки становится проблемно. Т.е. надо вначале внести правку в шаблонах Vue, затем пересобрать проект и постараться не сломав перетянуть его на CMS. Если это делается регулярно и обслуживается одной командой разработчиков, тогда можно настроить непрерывную интеграцию с автоматической пересборкой шаблона CMS, что по-логике является оптимальным решением. Но если с этим придется будет работать сторонним программистам, которым ради внесения небольшой правки в верстку сайта, придется будет научиться разбираться в компонентах Vue, в различных конфигах бандлеров и пр., то в таком случае, есть высокая вероятность, что эти разработчики не будут сильно разбираться и просто воткнут какой-нибудь костыль прямо в код шаблона (см. теорию разбитых окон).
Почему я обратил внимание на AlpineJS
В общем для подобных ситуаций я стал искать более подходящее решение, которое не требовало бы знания кучи сторонних утилит и имело минимум зависимостей. В процессе поисков наткнулся на быстро набирающий популярность проект AlpineJS, который представляет собой небольшой JS микрофреймворк, позволяющий реализовать любую интерактивность в реактивном стиле, как и в React/Vue/Angular.
Лично меня AlpineJS заинтересовал благодаря некоторым его особенностям:
- Декларативный синтаксис, во многом схожий с Vue, т.е. многим веб-разработчикам данный подход будет знаком.
- Работает напрямую с DOM моделью (т.е. без виртуальной DOM-модели), что позволяет беспроблемно работать со сторонними скриптами и JS-библиотеками.
- Минималистичный и очень простой API позволяющий быстро ознакомиться тем программистам, которые будут в дальнейшем сопровождать код.
- Нет обязательной необходимости в каких-либо транспиляторах, бандлерах и пр., т.е. количество необходимых зависимостей сведено к минимуму.
Кстати, хочу заметить, что разработчики AlpineJS явно вдохновлялись Vue, ибо даже в простейших примерах заметна схожесть. Вот взгляните на простой пример счетчика на Alpine и на Vue:
<!-- Пример на AlpineJS -->
<div x-data="{ count: 0 }">
<button x-on:click="count++">Increment</button>
<span x-text="count"></span>
</div>
<!-- Пример на Vue -->
<script setup>
import { ref } from 'vue'
const count = ref(0);
</script>
<template>
<button v-on:click="count++">Increment</button>
<span v-text="count"></span>
</template>
Как видите, похожего немало, но напомню, что хоть Vue и AlpineJS имеют схожие черты, у них разные весовые категории и они заточены под разные задачи. Хотя не могу не отметить, что разработчики Vue пытались сделать свой минималистичный вариант Vue в виде Petite-Vue (как альтернативу AlpineJS), но судя по коммитам, проект видимо давно заброшен. А вот AlpineJS активно развивается.
Расширения AlpineJS
Хоть AlpineJS и является микрофреймворком, но функционал расширения в нем все-таки заложен и более того, некоторые плагины развиваются самой командой разработчиков AlpineJS.
Из множества официальных плагинов, на деле я успел поработать пока что с двумя: Intersect и Persist.
Intersect работает поверх IntersectionObserver и предоставляет возможность удобно, декларативно и в реактивном стиле реагировать на пересечения элемента с его родителем или областью видимости документа. Это очень удобно, когда допустим нужно запустить какую-либо анимацию, во время скролла.
Хороший пример для наглядности как-раз представлен у них в документации:
<div x-data="{ shown: false }" x-intersect="shown = true">
<div x-show="shown" x-transition>
I'm in the viewport!
</div>
</div>
Плагин Persist представляет собой менеджер состояний, благодаря которому можно хранить состояние в LocalStorage или SessionStorage, а также взаимодействовать с хранимыми значениями реактивно. По назначению в чем-то схоже с Vuex или Pinia из мира Vue.
С остальными официальными плагинами я пока еще не работал, но думаю так или иначе еще успею с ними познакомиться. Да и в общем, тема плагинов к AlpineJS достойна более подробного рассмотрения в виде отдельной статьи.
AlpineJS и Tailwind
Вот совсем не могу не отметить тот момент, что AlpineJS очень гармонирует при работе с Tailwind. Эти два фреймворка прям отлично дополняют друг друга, при этом как-бы странно не звучало, оставаясь в рамках нативной HTML разметки.
Конечно, что-то подобное с первого раза может испугать:
<div class="flex flex-col justify-center gap-2 bg-emerald-50 px-4 py-6" x-data="{ shown: false }" x-intersect="shown = true">
<div class="text-white text-2xl md:text-3xl lg:text-4xl" x-show="shown" x-transition>
I'm in the viewport!
</div>
</div>
С другой стороны, тут вам и реактивность, тут и адативность, тут весь и UI и при этом все это фактически представлено в виде HTML разметки. Соответственно с этим беспроблем будет работать любая IDE, умеющая работать с HTML. Ну и тупо различные парсеры HTML тоже вполне легко могут работать с этим, да и с поисковыми системами будет попроще.
Заключение
Для меня AlpineJS быстро стал одним из тех инструментов, который я стал активно использовать в разработке. Его на деле оказалось удобно использовать в череде тех задач, где Vue избыточен. В тоже время для разработки самодостаточных веб-приложений он малоприменим, поскольку в нем нет поддержки разделения кода на отдельные самодостаточные веб-компоненты, да и возможности в нем ограничены.
На мой взгляд AlpineJS ни в коем случае не конкурирует с Vue/React/Angular, а просто занимает свою нишу применения, фактически являясь маленьким карманным JS-микрофреймворком, который не требует никаких зависимостей. И соответственно в своей профессиональной деятельности вы можете использовать любой из этих инструментов, подбирая подходящий в зависимости от задач. А как-никак, подбор оптимального стека технологий для проекта - это тоже важный профессиональный навык, который нужно развивать.