Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Попробую приноровиться к хабру и залью сюда перевод статьи с другого своего ресурса.
Это весьма самоуверенное, но, надеюсь, честное и точное сравнение 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.