rails
April 15, 2022

Rails 7: три мощных ответа JavaScript’у в 2021+

Перевод статьи "Rails 7 will have three great answers to JavaScript in 2021+" David Heinemeier Hansson (DHH) от 6 сентября 2021 года.

Rails изначально был бескомпромиссно full stack фреймворком Мы постоянно стремились включить максимально много решений по умолчанию по всем основным вопросам инфраструктуры, возникающим в современной веб-разработке. От общения с БД и отправки / получения электронных писем до веб-сокетов, рендеринга HTML и взаимодействия с JavaScript. Такая стратегия была ключом к успеху Rails, но она также остается постоянным источником споров. Что лишнее? Чего не хватает?

Для последовательного ответа на этот извечный вопрос надо обратиться к доктрине Rails, особенно к третьему столпу The Menu Is Omakase. Вот почему мы беспокоимся о значениях по умолчанию, а также почему так важна возможность их изменения.

На протяжении многих лет не было более обширных споров по поводу значений по умолчанию или более тщательного изучения вариантов, чем в части JavaScript. Особенно в последнее время, когда постоянная текучка и фундаментальные изменения привлекли внимание к новым возможностям. Но после долгих экспериментов я считаю, что теперь у нас есть надежный ответ для Rails 7.

Rails 7 по умолчанию использует Hotwire и import-map

В Rails 7 мы заменяем Webpacker, Turbolinks, UJS на import maps с Turbo и Stimulus из Hotwire. Это самое полное решение, которое мы когда-либо поставляли из коробки. Turbolinks + UJS обеспечили базу для того, чтобы приложения чувствовали себя так, будто они SPA-приложения, но как только вам надо добавить динамики - можно «Использовать Собственный JS-Фу».

Hotwire гораздо более амбициозна. Turbo взял основы Turbolinks и пошел намного дальше с отправкой форм, фреймами и потоками (streams). Теперь вы действительно можете реализовать большинство динамических элементов только с помощью Turbo (без написания какого-либо пользовательского JavaScript!). Кроме того, есть Stimulus - скромный JavaScript-фреймворк для HTML, который у вас уже есть (вставленный в HTML со стороны Rails). Это полноценная альтернатива тяжелым клиентским приложениям JavaScript, которые общаются с серверной частью в формате JSON.

В Rails 7 Hotwire работает через HTTP2, ES6/ESM и import maps. Я подробно объяснял, почему эта троица меняет современный web и не буду повторяться здесь. Отмечу только, что эти технологии вместе с Hotwire и JavaScript CDN-based package management являются крутыми фичами. Предлагаю ознакомиться с этим в Alpha preview: Modern JavaScript in Rails 7 without Webpack.

HEY работает на этом стеке уже несколько недель(в 2021 - прим. переводчика) и это просто пэрсик (полный отчет ожидается скоро!). Никаких отдельных процессов для сборки, сложных конфигов и nodejs. Мгновенные обновления и live reload без потери производительности или иных возможностей. Это лучшее, что мы получали в Basecamp.

Я говорю «для нас», потому что HEY явно разрабатывался с учетом этого видения. У нас никогда не было вороха JavaScript. Мы никогда не использовали транспайлеры вроде JSX. Это было место, где оттачивался Hotwire. Так что НЕТ СОМНЕНИЙ в том, что это прекрасно работает.

В то же время HEY не отклонение от нормы. Он конкурирует с Gmail, который годами считался приложением, которое определённо должно иметь толстые фреймворки на стороне клиента, кучей JSON и распоследними фишками транспайлеров.

Gmail загружает около трех мегабайт JavaScript для отображения своего почтового ящика. HEY загружает менее шестидесяти килобайт. Если вы можете создать конкурента Gmail с помощью данного стека и получить широкое одобрение со стороны десятков тысяч платящих клиентов, вы, вероятно, сможете создать с его помощью практически чего угодно.

Значит это отличный выбор для включения в Rails по умолчанию.

В Rails 7 полная поддержка традиционной упаковки JS

Но еще одна из основ Rails заключается в том, что мы пытаемся «Возвести большую палатку». Hotwire и import maps категорически не будут ответом на всё. Это отличный ответ. Это ответ по умолчанию. Но это не единственный ответ. Rails должен стать прекрасным фреймворком для разработки обычных single-page приложений на JavaScript — в комплекте с маршрутизацией на стороне клиента, сложным управлением состоянием и всеми другими сложностями этого подхода. И это будет.

Таким образом, в Rails 7 мы одновременно предлагаем отличный способ “по умолчанию” избежать работы со всей настройкой node/npm/bundling и предлагаем полностью поддерживаемый альтернативный вариант, который охватывает все эти вещи. Но мы собираемся сделать это иначе, чем раньше.

Webpacker родился почти пять лет назад с миссией сделать сборку JavaScript простой в использовании для разработчиков Rails, которые не всегда были заинтересованы в том, чтобы стать экспертами по JavaScript. Поскольку ES6 требовал транспайлинга для широкой поддержки в браузерах в то время, а npm требовался для доступа к экосистеме пакетов для node, не было иного способа обойти это. Мы могли либо принять эту реальность, либо сделать Rails лишь API для таких приложений. Мы выбрали «объятия».

Но сегодня компромиссы, сделанные для Webpacker, начинают иметь гораздо меньше смысла. Он как бы застрял в вязкой середине между двумя ясными путями. Существует новый путь полного отказа от конвейера (pipeline), который намного проще в настройке, имеет меньше зависимостей и более удобное (менее неудобное) разделение труда между Ruby и JavaScript. И еще есть полный путь, когда мы вообще не пытаемся скрыть или обернуть сложности JavaScript. Мы просто предоставляем мост, с помощью которого сгенерированный JavaScript можно использовать в приложении Rails, но оставляем экосистеме JavaScript возможность предоставить свои ответы.

Я написал первоначальную версию Webpacker, и мы успешно использовали ее как в Basecamp, так и в HEY, и она хорошо послужила сообществу в качестве переходного этапа между прошлым и настоящим. Но я не вижу причин, чтобы компромиссные решения, сделанные пять лет назад, хорошо служили настоящему или будущему.

Вместо этого Rails 7 готов предложить альтернативный путь, который намного проще и гораздо более привычен с точки зрения мира JavaScript. Вы пишете JavaScript, сохраняя исходный код в app/javascript, запускаете скрипты сборки с помощью определений в package.json, а затем передаете результаты конвейеру (pipeline) в app/assets/build, чтобы их можно было использовать в приложении с учетом digest-stamp и CDN-preface. Так работает гем jsbundling-rails.

Этот гем обеспечивает простую настройку, необходимую для esbuild, rollup.js или Webpack. Он устанавливает основные зависимости для выбранного сборщика, готовит файл конфигурации, если это необходимо, и опирается на соглашения о точке входа по умолчанию в app/javascript/application.js и сборках, размещенных в app/assets/builds. Это все! Ответственность за управление и обновление зависимостей возлагается на разработчика.

Вероятно, вам следует выбрать именно этот путь, если вы собираетесь полностью использовать что-то вроде React с JSX или другой инфраструктурой JavaScript, требующей этапа транспайлинга. Можно сделать React с import maps, но это будет через htm, и это может быть слишком большим компромиссом для тех, кто «идет ва-банк».

Если вы используете Webpacker, то вам будет очень просто переключиться на один из сборщиков, доступных через jsbundling-rails. Вам даже не надо ковыряться в Webpack. Все сборщики работают одинаково: берешь точку входа, производишь билд. Сначала мы пошли по этому пути в Basecamp 3, перейдя с Webpacker на esbuild. Но в HEY мы сделали полный шаг к import maps. Ни один из вариантов не требовал больших усилий. JavaScript остается JavaScript. Вам, в основном, надо будет настроить несколько путей импорта.

Если у вас еще нет особых предпочтений, но вы знаете, что вам нужна сборка JavaScript, я бы посоветовал вам начать с esbuild. Он чертовски быстр и поставляется предварительно настроенным для JSX и даже TypeScript.

В Rails 7 будет три четких варианта для JavaScript

Наконец, у вас есть возможность просто использовать Rails в качестве API и отдельного JavaScript приложения в другом проекте и репозитории. Rails давно поддерживает такой вариант с --api и будет продолжать это делать. Но это не то, что я бы рекомендовал для малых и средних команд, но если вы работаете в крупной организации, стремящейся к созданию SPA с высокими стенами между клиентскими и внутренними отделами - это может иметь смысл.

Такова история JavaScript в Rails 7 и далее. Путь по умолчанию с Hotwire и import maps, альтернативный путь с использованием тонкой интеграции с одним из популярных сборщиков JavaScript и, наконец, строгий путь API с отдельным репозиторием для фронта.

Три надежных ответа на реальность современной веб-разработки в 2021 году.

Вскоре выйдет альфа-версия Rails 7, и мы намерены отпраздновать финальный выпуск до конца года. Пожалуйста, помогите нам достичь этого, помогая тестировать и улучшать эти выпуски!

Оригинал: Rails 7 will have three great answers to JavaScript in 2021+ от 6 сентября 2021 года.

Автор: David Heinemeier Hansson (DHH)