Hyperstack vs Hotwire
Перевод статьи "Hyperstack vs Hotwire" @catprint aka Mitch VanDuyn от 26 февраля 2021 года.
Это весьма самоуверенное, но, надеюсь, честное и точное сравнение Hyperstack и Hotwire.
Прежде всего, что это за вещи?
Оба решения помогают затащить современный UI в Rails
Оба завязаны на Websockets для получения уведомлений об изменении состояния.
Hyperstack
- Всё написано на Ruby (включая клиентский код)
- Под капотом используется React для построения UI с возможностью доступа к библиотекам React
- Легко поддерживает синхронизацию моделей Rails между UI и сервером. Зачастую без дополнительного кода
- Убирает необходимость написания контроллеров (но при желании можно продолжать их использовать)
- Отдает максимально возможное количество работы на сторону клиента
- Предоставляет мощный механизм контроля доступа к данным, построенный на политиках “Pundit"
- Может использоваться в существующих Rails-приложениях
Hotwire
- Это следующий виток эволюции Rails Turbolinks
- Расширяет стандартную MVC систему Rails за счет передачи инкрементальных обновлений на уровень представления
- Использует традиционные Rails подходы
- Оставляет бóльшую часть работы на стороне сервера, делая клиентскую часть очень лёгкой
- Устраняет большую часть JS-кода (но не весь), которую вам может потребоваться писать
- Поддерживается DHH и, предположительно, сообществом Rails
Чтобы бегло сравнить данные технологии, я обратился к простому приложению “Tweet” (https://gorails.com/episodes/hotwire-rails) и создал такое же на Hyperstack. На заметку: данный дизайн UI компонентов не моя идея, я позаимствовал код с минимально возможными изменениями
Поскольку одна из основных целей Hyperstack состоит в уменьшении общего объема кода, начнём рассмотрение с числа строк. Сгененированные файлы и шаблоны, такие как layout и стили включать не будем, поскольку они совпадают.
Hyperstack - 78 lines vs — Hotwire — 156
Но строки - это еще не всё, какой инструмент будет легче в понимании и поддержке?
Рассмотрим, как каждый фреймворк реализует “Tweet Card”, отображающий твит и позволяет обновлять счетчики "лайков" и "ретвитов".
Hyperstack:
Hotwire:
Пока что оба приведенных участка кода очень похожи.
Hyperstack определяет React-компонент, берущий твит в качестве параметра, и формирует код на основании DSL. Этот DSL отражает нижележащую HTML-разметку с дополнительными компонентами в вашем приложении. Например EditTweet компонент, подключаемый в 11 строке.
Hotwire использует ERB для генерации HTML, используя ряд вспомогательных функций, таких как turbo_frame_tag
и т. д.
Как и React, Hyperstack является декларативным и “state-driven” инструментом. Когда пользователь нажимает на кнопку “изменить”, устанавливается состояние “editing”, что в свою очередь заставляет компонент перерисовать и подключить EditTweet компонент (строка 14). EditTweet в свою очередь эмитит события save или cancel, оба из которых возвращают “editing state” в состояние false. Всё это определяется и исполняется на стороне клиента.
Цель же Hotwire заключается в реализации логики на сервере таким образом, что нажатие на “Edit” просто отправляет запрос на сервер, который выполняет обновление компонента.
Когда пользователь нажимает “Like” или “Retweet”, Hyperstack обрабатывает событие с помощью .on(:click)
, и просто зовет ActiveRecord increment!
и обновляет счетчик твита. Под капотом Hyperstack занимается поддержанием локальной копии твита в синхронизированном с сервером состоянии и пересылает все изменения всем участвующим клиентам (браузерам)
Hotwire тем временем выполняет обновления счётчиков так же, как и edit функция: передаёт работу серверу и требует наличия когда, обрабатывающего это. И действительно, тут есть три контроллера, которые выполняют работу по обработке изменений твита:
Таким образом, не смотря на то, что код Hyperstack изначально был немного длиннее, пользовательский интерфейс — это еще не вся история. И чтобы html.erb действительно заработал, необходимо ещё 70+ строк и что ещё хуже UI-логика оказывается размазана по четырём файлам.
Но мы ещё не закончили. В добавок к .erb файлу и контроллерам нам также необходимjson
файл, который выполняет функции связующего API. К счастью, Hotwire поставляется с jbuilder, так что это всего лишь 2 строки когда, но его надо написать и поддерживать.
Погодите, мы ещё не закончили. Чтобы Hotwire знал, что ему необходимо разослать изменения клиентам, вам надо добавить три дополнительных колбэка (after_...
) в twitter.rb
Мы закончили? Почти. Остался ещё один файл. Помните про контроллеры? Теперь к ним надо добавить роуты, а это еще 3 строки в другом файле. Честно говоря, Hyperstack тоже требует несколько строк (две если быть точным) в routes.rb
, но они никогда не будут меняться в течении жизни приложения.
Прежде чем я продолжу, давайте посмотрим с другой стороны. Допустим у вас уже есть рабочее приложение, к которому вы хотите добавить кнопку “Like”
Что для этого нужно?
Во-первых в обоих фреймворках вам надо добавить атрибут в модель данных, создав и выполнив миграцию. (Рельсы!)
Далее для Hotwire необходимо:
- добавить ресурс в роуты
- добавить контроллер (как мы видели это 14 строк)
- не забыть обновить
json
, добавив в него новый атрибут - и наконец добавить
button_to
тэг в_tweet.html.erb
Мы затронули четыре файла и добавили 16 строк кода, используя знания о шести подсистемах Rails - action controller, view helpers, jbuilder, active record и router - написали собственный код на Ruby, HTML и ERB.
Как выполняется та же задача на Hyperstack?
Как только закончили с миграциями надо добавить только:
BUTTON { "Likes (#{tweet.likes_count})" } .on(:click) { tweet.increment!(:likes_count) }
Для чего требуется только понимание функции active record increment!
и HyperComponent DLS, что напрямую относится к выполняемой работе.
В чем подвох?
Подвоха нет, просто другие цели. Hyperstack строился для максимизации эффективности программиста и для передачи работы с сервера на сторону клиента. Он достигает целей используя один замечательный язык, опираясь на Rails и используя девиз Rails о “convention over configuration” для устранения ненужных шаблонов.
Заявленная цель Hotwire состоит в том, чтобы сохранить контроль за приложением на сервере и он достигает её ценой ценой усложнения поддержки и понимаемости приложения. Он также использует более консервативный подход в архитектуре приложения, вместо того, чтобы отказываться от контроллеров и заменять ERB файлы на собственный DSL. Он основан на проверенных и надёжных техниках Rails, который привычны многим разработчикам.
Некоторые другие соображения
Это маленькое упражнение, но оно позволяет увидеть как две разные системы выполняют свои задачи. Я считаю, что с Hotwire становится сложнее, с Hyperstack — проще. Я не могу этого доказать, но как я уже сказал это самоуверенная статья.
Ещё одно соображение касательно ценности участия в экосистеме React. Фундаментальная архитектура React, как декларативной и "state-driven" системы, делает результирующий код невероятно простым для написания и понимания. Я считаю, что гораздо проще (разумеется, после того, как преодолел порог вхождения) создавать высокофункциональный и поддерживаемый код в декларативном стиле. Более того, существует множество готовых компонентов React для решения самых разнообразных задач, что ещё больше сокращает объём кода, который необходимо писать и поддерживать.
И последнее: о ценности разработки на одном языке. Многие не считают это существенным, а работу программиста с несколькими языками и системами - само собой разумеющимся. Но это не так. Постоянное переключение контекста заставляет программиста растрачивать ценную энергию и думать о деталях реализации, вместо того, чтобы думать о системе в целом. Нет ничего, что могло бы сделать один язык лучше для разработки пользовательского интерфейса, а другой - для серверной части. Есть инструменты для компиляции практически любого языка на любую платформу, так почему бы не выбрать один язык, который можно использовать в масштабах всей системы? И если вы собираетесь выбрать язык, то Ruby трудно превзойти.
Оригинал: Hyperstack vs Hotwire от 26 февраля 2021 года.
Автор: @catprint aka Mitch VanDuyn
От переводчика
Мы решили выбрать эту статью для того, чтобы осветить различные современные течения во фронтендной части Rails. Мы не определились до конца с подобными инструментами, однако на нескольких проектах начали использовать Stimulus и двигаемся в сторону Hotwire.