[Перевод] Как Phoenix убивает React

393bdc82063645699c7fa2685252430a.png

Около полутора лет назад мы написали внутренний инструмент для корпоративных анонсов. Изначально в нём использовался 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-приложения на отдельном фреймворке. Мало того, что готовый продукт получился таким же классным, так мы ещё и стали быстрее добавлять новые возможности, смогли быть уверенными в тестах и легче привлекать разработчиков для участия в проекте. В общем, я думаю, это была большая победа.


А вы отказывались от каких-либо фронтенд-фреймворков в последнее время?


Заключение от Вуншей


Друзья! Следующая статья про создание блога на Фениксе через неделю. Сегодня же мы решили обсудить другую интересную тему, связанную с этим фреймворком.


Напоминаю, что мы проводим конкурс с классным призом для победы в котором вам нужно опубликовать классную статью об Эликсире на Хабре. А также призываю вас активнее подписываться на рассылку. Дважды в неделю мы отправляем новые статьи на почту, которых ещё нет в открытом доступе на сайте! Спасибо всем, кто остаётся с нами!


* Заголовок для активации бурных обсуждений, наполненных радостью и добром, в комментариях.

Комментарии (10)

  • 21 ноября 2016 в 09:54

    +2

    Как быть с не-хтмл клиентами и медленным каналом связи?

    • 21 ноября 2016 в 10:49

      0

      1. Оставить JSON API дня сторонних клиентов.
      2. В этом случае нужно решать задачу, исходя из технических ограничений. Например, не использовать описанный в статье метод. :)
  • 21 ноября 2016 в 10:52

    0

    А пробовали поюзать с пингом ближе к секунде? Приложение не потеряет отзывчивость до уровня раздражающего неудобства?
    • 21 ноября 2016 в 10:55

      0

      Наверное, в этом случае и React не сильно поможет? А количество дааных в HTML и JSON представлениях, предположу, что не сильно различается.
      • 21 ноября 2016 в 10:59 (комментарий был изменён)

        0

        React может поможет тем что ответ на действие пользователя будет мгновенным (Откроется нужная страничка, на ней нарисуется loading, по ощущениям такое поведение страницы воспринимается пользователем менее болезненно). Или все данные могут храниться в каком-нибудь store — и тогда будет только один запрос который получит все нужные данные.
        • 21 ноября 2016 в 11:18

          0

          Если нужно полноценное SPA с определёнными техническими требованиями, то да, без фронтенд-фреймворка не обойтись. Если нужно добавить «живости» сайту, то можно сделать проще. Как именно? Об этом и рассказано в статье.
          • 21 ноября 2016 в 11:20

            0

            Да я не критиковал подход — я просто спросил как оно выглядит, насколько юзабельно. Секунда, пожалуй, многовато —, но 500ms не слишком редкий пинг на мобильном.
  • 21 ноября 2016 в 11:15

    0

    «Другим больным местом при работе с кодом React было тестирование. Так как приложение и клиент были разделены, нужно было быть уверенными, что ответы нашей тестовой имитации сервера всегда актуальны.» Лолшто.
    Это проблема всегда есть при разработке SPA приложения.
    • 21 ноября 2016 в 11:16

      0

      И они достаточно изящно избавились от этой проблемы. Так можно делать не всегда, но если ситуация позволяет. то почему бы и нет?
    • 21 ноября 2016 в 11:32 (комментарий был изменён)

      0

      + Есть подозрение, что такое должно решаться ui тестами.

© Habrahabr.ru