rails
March 30, 2021

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.