Около полутора лет назад мы написали внутренний инструмент для корпоративных анонсов. Изначально в нём использовался Phoenix для бэкенда и React для фронтенда. Тем самым мы получали преимущества Redux и каналов Phoenix при доставки обновлений в браузер в реальном времени.
Это позволило получить великолепный живой интерфейс, но снизило скорость разработки и стало причиной малого количества участвующих в процессе разработчиков. Около трёх месяцев назад мы приняли решение выкинуть React и вернуться к серверному рендерингу.
Почему мы решили заменить React
Обновление в реальном времени позволяет лучше погрузиться в работу с приложением, но при этом имеет дополнительные издержки.
Стоимость разработки
Вместо того, чтобы добавлять новую возможность в одном месте, нам нужно было заниматься ей и в части API, и в части UI. Это также означало, что каждый разработчик, желающий добавить свой вклад в проект должен знать и React, и Phoenix, что отбивало у них охоту попробовать включиться в работу.
Тестирование
Другим больным местом при работе с кодом React было тестирование. Так как приложение и клиент были разделены, нужно было быть уверенными, что ответы нашей тестовой имитации сервера всегда актуальны. На практике это не было серьёзной проблемой, но несколько раз всё же вставило палки в колёса, уменьшив наше доверие тестам.
Внесение вклада в проект
Наконец, мы хотели, чтобы больше людей могло принимать участие в работе над проектом. Мы обнаружили, что реализация функционала в двух местах намного трудозатратнее по сравнению с работой в единственном месте. А пытаться координировать бэкенд- и фронтенд-разработчиков довольно утомительно. Это особенно важно, поскольку работа над этим приложением происходит в наше «время для развития».
Процесс замены
Благодаря тому, что у нас уже был готовый к использованию API, мы смогли переписать страницы на Phoenix и развернуться на продакшене, не затрагивая существующий на React фронтенд. Так как приложение по большей части представляет собой CRUD, большинство страниц были просто перекопированы один-в-один, лишь заменяя className
на class
и блоки {}
на <%= %>
.
В местах, где нам был нужен JavaScript, мы пошли проторенной дорожкой «вкрапления» кусочков на нём. Лучший пример такого подхода — живое обновление комментариев. Всякий раз, когда комментарий создаётся на бэкенде, мы транслируем его всем пользователям. Вместо того, чтобы отправлять JSON, мы создаём live-html
канал, через который передаём обновления пользователями в виде HTML. Вот JavaScript код прямиком из приложения:
import socket from './socket'
const channel = socket.channel('live-html', {})
channel.join()
.receive('ok', function(resp) { console.log('Joined successfully', resp) })
.receive('error', function(resp) { console.log('Unable to join', resp) })
channel.on('new-comment', payload => {
$(`[data-announcement-id='${payload.announcement_id}'] .comments-list`)
.append(payload.comment_html)
})
Это удивительно небольшое количество кода на JavaScript, обеспечивает огромный кусок функциональности нашего приложения. Подобная стратегия генерации HTML на сервере и транслирования его клиентам гораздо проще, чем написание полноценного фронтенд-приложения с такими же возможностями.
Мы также добавили сюда Turbolinks, что сделало обновление страницы очень плавным и позволило нам получать ощущение SPA.
Результаты
Полная миграция была относительно безболезненной. Мы пришли к тому, что за несколько месяцев к проекту присоединилось больше людей, чем за весь год использования фронтенда на React. Тесты стало писать гораздо легче, в то же время они стали гораздо надёжнее. Ведь теперь не нужно боятсья, что тестовые ответы сервера отличаются от настоящих.
Несмотря на то, что многие сотрудники компании знали о происходящей миграции, мы не стали никому говорить, что вылили изменения в продакшен. Ни один человек не упомянул о заметной разнице. Также никто не понял, что используемое ими приложение больше не основано на React. Всё благодаря скорости Phoenix с его значительно меньшим временем отдачи страницы и отсутствию загрузки большого куска данных фронтенд-приложения на React.
Усвоенные уроки
В конце нашей работы мы поняли и доказали себе, что можем писать приложения на Phoenix с серверным рендерингом, которые будут так же великолепно работать, как и SPA-приложения на отдельном фреймворке. Мало того, что готовый продукт получился таким же классным, так мы ещё и стали быстрее добавлять новые возможности, смогли быть уверенными в тестах и легче привлекать разработчиков для участия в проекте. В общем, я думаю, это была большая победа.
А вы отказывались от каких-либо фронтенд-фреймворков в последнее время?
Заключение от Вуншей
Друзья! Следующая статья про создание блога на Фениксе через неделю. Сегодня же мы решили обсудить другую интересную тему, связанную с этим фреймворком.
Напоминаю, что мы проводим конкурс с классным призом для победы в котором вам нужно опубликовать классную статью об Эликсире на Хабре. А также призываю вас активнее подписываться на рассылку. Дважды в неделю мы отправляем новые статьи на почту, которых ещё нет в открытом доступе на сайте! Спасибо всем, кто остаётся с нами!
Комментарии (37)
Anarions
21.11.2016 10:52А пробовали поюзать с пингом ближе к секунде? Приложение не потеряет отзывчивость до уровня раздражающего неудобства?
jarosluv
21.11.2016 10:55Наверное, в этом случае и React не сильно поможет? А количество дааных в HTML и JSON представлениях, предположу, что не сильно различается.
Anarions
21.11.2016 10:59React может поможет тем что ответ на действие пользователя будет мгновенным (Откроется нужная страничка, на ней нарисуется loading, по ощущениям такое поведение страницы воспринимается пользователем менее болезненно ). Или все данные могут храниться в каком-нибудь store — и тогда будет только один запрос который получит все нужные данные.
jarosluv
21.11.2016 11:18+1Если нужно полноценное SPA с определёнными техническими требованиями, то да, без фронтенд-фреймворка не обойтись. Если нужно добавить «живости» сайту, то можно сделать проще. Как именно? Об этом и рассказано в статье.
Anarions
21.11.2016 11:20Да я не критиковал подход — я просто спросил как оно выглядит, насколько юзабельно. Секунда, пожалуй, многовато — но 500ms не слишком редкий пинг на мобильном.
svboobnov
21.11.2016 22:41Секунда тоже может случиться, когда ближайшая сота вырубилась, а вокруг туман густой (через туман радиосигнал плохо проходит, много пакетов теряется).
Пользуюсь 3G — модемом, и иногда такое наблюдал.
justboris
21.11.2016 11:59+4Ничто не мешает показывать loading и в случае server-rendering.
Например, так работает Github (при навигации по папкам репозитория сверху показывается синий прогрессбар).
markfrost
21.11.2016 11:15+2«Другим больным местом при работе с кодом React было тестирование. Так как приложение и клиент были разделены, нужно было быть уверенными, что ответы нашей тестовой имитации сервера всегда актуальны.» Лолшто.
Это проблема всегда есть при разработке SPA приложения.jarosluv
21.11.2016 11:16+1И они достаточно изящно избавились от этой проблемы. Так можно делать не всегда, но если ситуация позволяет. то почему бы и нет?
Veikedo
21.11.2016 11:32+ Есть подозрение, что такое должно решаться ui тестами.
Anarions
21.11.2016 11:38+1Ну, оно и решается, думаю в ситуации описанной автором не нравилось то что при изменении в API все изменения надо было дублировать в моках, и эту проблему решили просто избавившись от всей логики в UI
saggid
21.11.2016 12:51+1Очень верное мышление, на мой взгляд. Мы тут пилим один большой проект, и я когда думал над его архитектурой, то примерно также всё было продумано.
Суть примерно такая: 90% сайта — это обычные статичные страницы, которые генерируются сервером на основе обычных шаблонов. Но некоторые части проекта используют JS компоненты: в основном это Riot.js. По большей части, наша стратегия — это использовать сложную логику на основе js только в конкретных ключевых точках приложения, которые подразумевают большое количество динамических изменений, интерактивное поведение, и так далее.
tot0ro
21.11.2016 13:51+3Как по мне так название статьи «Как Phoenix убивает React» вводит в заблуждение.
У меня к вам пара вопросов:
— чем именно вам мешает React ???
— как Phenix будет его убивать на Node, Ruby и etc???
— вам не кажется что изначально был неверно выбран инструмент или подобрана команда???
После прочтения статьи сложилось впечатление что у вас мало хороших front-end разработчиков и функционал приложения довольно таки посредственный и не предполагает высокой степени активности.
Попробуйте на серверном рендеринге с минимальным js сделать торговую панель для трейдера с 3-5 индикаторами. Я думаю в этом случае React сможет более полно раскрыть свой потенциал.jarosluv
21.11.2016 14:56На картинки для привлечения внимания более точный заголовок. :)
А статья — перевод. Самое главное, что такой подход скорее всего можно применить и на других языках. Не добавлять зависимости, если задачу можно решить из коробки.
Ckomop0x
21.11.2016 13:52+1Тезис: Авторы описали как переехали с фронта на бэк и стало проще всё тестировать и писать в одном месте, но зачем тогда такое громкое название про React и Phoenix? Возможно, если у них нет мобильных клиентов и приложений, PWA и ограничения по трафику это удобно… но в нынешнее время куда лучше закешировать всё на клиенте и оптимизированно подтягивать данные в готовый интерфейс, а не генерить тонны трафика повторяющегося html.
Вывод: сложилось впечатление, что им просто было лень и они решили всё упростить.justboris
21.11.2016 13:58Громкое название придумали переводчики.
Оригинально статья называлась "How We Replaced React with Phoenix", убивать никто никого не собирался
jarosluv
21.11.2016 14:53-5Прошу простить меня за столь громкий заголовок. Примечание по этому поводу в самом конце страницы. :)
yul
27.11.2016 19:22+2Вывод: сложилось впечатление, что им просто было лень и они решили всё упростить
Что в этом плохого-то?
nwalker
21.11.2016 14:10+1внутренний инструмент для корпоративных анонсов.
React для фронтендаДальше пост можно не читать, все и так понятно.
jarosluv
21.11.2016 14:52Суть статьи как раз в том, чтобы не всегда нужно усложнять архитектуру приложения и в некоторых случаях можно обойтись решением прямо из коробки, которое ещё и проще. Зачастую это касается как раз подхода использования фронтед-фреймворков, просто чтобы было.
nwalker
21.11.2016 15:43+3На мой взгляд, здравомыслящемум человеку это и так понятно, и конкретные тулзы тут вообще ни при чем.
Вообще, я этот пост читал сразу после написания и мне хотелось разбить себе лицо руками — это просто эталон хипстерства. "Давайте мы сначала сделаем фронтенд на ненужном нам new and shiny реакте, потом удивимся, что так трудно, перепишем на new and shiny фениксе и напишем пост, какой замечательный феникс и как трудно с реактом".
Fen1kz
21.11.2016 15:21+5Не верю. Окей, молодцы вкрапляете js маленькими кусочками.
Дальше таких кусочков будет все больше и больше, а давайте ещё комменты можно будет прокручивать, а давайте будет оповещалка о новом комменте, а что-то js не тянет, давайте jquery, а давайте нам галерею, давай, jquery плагином, а ещё это и вот то, и тут классный плагин, а что это сайт превратился в jquery монстра, который парсит куски html с сервера, а давайте перепишем все на ангуляр.
А тот будет тормозить, да и двусторонний биндинг нафиг нужен, давайте обратно на реакт.
baka_cirno
21.11.2016 15:29+1Если кто-то и убивает React (чего на самом деле и близко не происходит), так это набирающий популярность Vue.
serf
21.11.2016 18:08-1Vue (v2) содержит virtual dom как элемент оптимизации, а React только этим элементом и является (по сути просто продвинутый шаблонизатор), так что React не нужен от слова совсем.
orcy
21.11.2016 15:35+6Подождите убивать React, я на нем еще не ничего не сделал! Вот же ж JavaScript, полгода и библиотека в хайпе, а потом уже сразу considered harmful
yul
27.11.2016 19:24+1Можете уже на vue перебираться ) И да, я тоже не успел…
taujavarob
28.11.2016 16:30-1Можете уже на vue перебираться ) И да, я тоже не успел…
Там нет драйва. Весь драйв сейчас только на React.
Остальные просто скучноваты монстры. Вымирающие динозавры, пытающиеся хоть как-то противостоять React тем, чтобы дать всё из коробки, тем кто устал и не хочет «париться».
Имхо.
;-)
betsuni
21.11.2016 18:22+6Вот такие они js фреймворки: я еще ничего даже написать на реакте не успел, а он уже умирать начал.
Bimawa
22.11.2016 09:31+1Капец заголовок… один в один новости на канале Россия 1
Я прочитав статью не понял как Ваша навороченная версия PHP может убить Front-end фреймворк? Если Вы такие страшные убийцы фреймворков, что ж не убить и ваш новороченый PhoenHP? Один фиг его изучать тоже надо вашей команде.
ЛАЙК ЗА GITHUB PAGES! — Убьем фреймворки!!! CLEAN HTML!
В общем за статью спасибо, но посыл статьи в чем-то не понятен. Я не понял, толи в вашей компании работают люди которые ни чему не хотят учиться… толи… Слушайте статья не понятная вообще короче. Больше вопросов чем ответов. Почему бы вам не убить Google Chrome таким же способом?
Bimawa
25.11.2016 08:12+1О статья прям в тему: https://blog.daftcode.pl/hype-driven-development-3469fc2e9b22#.88ntkt501 Hype Driven Development
vintage
Как быть с не-хтмл клиентами и медленным каналом связи?
jarosluv
1. Оставить JSON API дня сторонних клиентов.
2. В этом случае нужно решать задачу, исходя из технических ограничений. Например, не использовать описанный в статье метод. :)
vintage
khim
Я на свой сайт тоже могу зайти по ГПРC, но утверждать вот прямо так сходу, что эта потребность нужна прям всем-всем-всем я не возьмусь. Очень может быть что и нет. Особенно если это корпоративный сайт и заходить на него откуда-нибудь из лесной глуши не нужно.
vintage