Как мы год живем без sprockets и с react

    Привет!

    Мы в taaasty.ru уже полтора года живем на react-е и почти год без sprockets. Это так здорово, хочу поделиться. За одно расскажу как работает react с рельсами в режиме prerender.

    image

    ReactJS


    Уже много сказано об этой технологии. Хочу лишь подтвердить, да, она прекрасна. Когда я пришел в проект он находился в стадии «давайте чинить эти баги, который вылезли из-з того что чинили вот тот». Во фронтенд желаний крутых фишек было тако много, что стало сразу понятно — мы не сможем учесть все возможные нюансы поведения в JS, а еще параллельно и править баги в легаси-коде без какого-то кардинального решения. И React полностью решает эту проблему.

    Сначала мы подключили react-rails и делали компоненты в рельсовом окружении на coffee. Быстро выявились следующие проблемы:

    1. JS код большой. Sprockets тормозной. Ожидания компиляции изменения становились все более и более утомительными.
    2. Фронтендер-у приходилось настраивать ruby on rails, и не смотря на общее окружение в vagrant, это лишние действия, трата времени.
    3. У фронтендер-а свой набор технологий — gulp, webpack и тп, свои пакеты, который в рельсы не подключишь.
    4. Кроме фронтендера с html работает еще и верстальщик, а бывает и дизайнер. Им вообще не до рельс. А еще верстку периодически нужно показывать заказчику и это проще делать на статичных страницах по ftp, чем запускать ради этого рельсы.

    В общем все шло к тому, чтобы фронтенд выделить в отдельный проект. Так и сделали. Весь React и JS перешел в отдельный репозиторий (его оставили открытым) — github.com/taaasty/web-static

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

    Так как фронт-репозитоирий оставили открытым, подключили бесплатный travis для билдов, и сделали скрипт для выкладывания готового демо-билда на gh-pages — taaasty.github.io/web-static таким образом всегда можно посмотреть последнюю рабочую версию верстки и скриптов.

    На этом этапе начали лучше понимать смысл поговорки «разделяй и властвуй».

    Sprockets


    Так как весь JS и CSS строятся в отдельном репозитории, в рельсах вообще пропала необходимость в сборке и sprockets (жуть). Статичные файлы подключаются в проект в виде git submodules:

    $ cat .gitmodules 
    [submodule "vendor/static"]
      path = vendor/static
      url = https://github.com/taaasty/web-static.git
      branch=develop
    
    $ ag vendor/static config
    config/application.rb
    40:    config.assets.paths << Rails.root.join('vendor/static/dist/stylesheets')
    41:    config.assets.paths << Rails.root.join('vendor/static/dist/scripts')
    


    во фронт репозитирии лежат готовые файлы сборки для стилей и яваскрипта, их и запрашиваем прямо из html:

    = javascript_include_tag 'desktop.production.js'
    = stylesheet_link_tag 'desktop.production.css'
    


    Теперь при развертывании нет прекомпиляции (assets:precompile не нужно), выкладывается все уже готовое. Длительность деплоя сократилась с 4-5 минут до 15 секунд.

    А как хорошо стало бакендерам — вставил компонент, передал ему параметры нужной структуры и нет тебе никакого геморроя с html и JS. Все это уже решили на фронте. Фактически бакенд стал таким одним большим API — api.taaasty.com

    react-rails


    Каждый, кто узнает что у нас весь фронт на реакте, в первую очередь спрашивает — ну и как-же пререндер? Да отлично, работает с полпинка, все страницы отдаются с уже готовой версткой.

    В ruby есть два рабочих движка для выполнения javascript (и пререндера компонентов). Это therubyracer (использует библиотеку libv8) и nodejs (реально запускает nodejs и отдает ему код на выполнение).

    • therubyracer. Ест память. Течет она. Средняя скорость выполнения компонента ~10-20ms, но иногда на каждый 10-ти тысячный запрос) происходит подвисон до 100-200 мс.
    • nodes безопасный способ выполнять JS код, НО, на каждое выполнение компонента (а их на странице может быть несколько) ruby запускает процесс nodejs (то есть загружает бинарный файл), скармливает исходный файл и забирает из STDOUT результаты. Средняя скорость выполнения компонента 50-80ms из которых большая часть уходит на подгрузку nodejs в память и его запуск.


    Мы остановились на therubyracer. На данный момент он рендерит 2-3 тысячи компонентов в минуту. Больше года полет отличный. react-rails остался в проекте и выполняет только функции пререндера.
    Share post
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 12

      0
      Каким образом JSON отдаете? ActiveModel Serializers или что-то другое?
        0
        Для API grape (swagger) + презентеры через grape-entity.

        Важный момент — сначала в названии презентеров исходили из названия модели, которую они презентуют (источника), потом стало понятно что именовать нужно согласно того компонента для которого эти данные готовятся. То есть одна и таже модель (публикация, например) по-разному представляется для разных компонентов.
        +4
        React на Node.JS, который собирается через Ruby on Rails. Просто мечта хипстера.
          0
          у нас в проекте для этого WebPack крутится, рельсы только сервят бандлы.
          +1
          А зачем пытаться рендерить react через rails?

          Мы уже сами пол года разрабатываем фронт как отдельный проект, по апи получаем все нужные данные, если нужен серверный рендеринг — запускаем сервер на ноде, который если нужно используем еще и как прокси для запросов к api(если все крутится на одном домене то можно этого и не делать, но для dev  окружения необходимо)

          Бекендеры рады — работают с чистыми данными, не парятся за  html и прочие фронтедреские штуки
          Мы(фронтендеры) тоже рады — от проекта к проекту работаем в привычном для себя окружении в независимости от того, что крутится на бекенде
            0
            Не во всех компаниях такие крутые UI разработчики, которым в радость запускать node. Я ниже написал у меня в компании лютые закоренеллые .NET-овцы которые и так на меня люто смотрят за grunt/gulp/bower и npm. А из всех UI разработчиков я такой один проактивный. Так что для некоторых рендеринг react через rails/.net/java/php/… это вполне такой компромис.
              0
              А сколько у вас по времени занимает запрос? Спрашиваю потому что наткнулся вот на такую интересную библиотеку, которыя обещает 32 кратный прирост приизводительности в случае интеграции node & в данном случае .net — tjanczuk.github.io/edge/#/35. Хотя когда речь об ~1.5 мс vs. ~0 мс, то наверное не особо важно =)
                0
                О, я это как раз искал, будем экспериментировать, спасибо.
              0
              У нас в компании все так же как и в статье, но на бекэнд .NET. Самый большой плюс это универсальный яваскрипт, все компоненты реюзабельны. Поверх функции которая рендерит копоненты на сервере еще сделали обертку чтобы в случае ошибки не вся страница ломалась, а только определенный компонент. Ещё один момент, наибольшое число проблем было с локализацией, например если бэкендшик добавил новый id для меню, который используется для локализованного текста а в локализации ещё этот текст не добавили, то у него выведется что-то типа `could not run Localization.menu[id][locale]`. Хотя если бы наши бекэнщики не были ленивыми, то писали бы юнит тесты вместо того чтобы жаловаться что теперь им нужно лезть в локализацию в чужой репозиторий и править там что-то, билдить, а то у них иначе страница ломается. Не понимают люди ещё что их ответственность заканчивается на добавлении id, а локализация и правильное отображение текста это уже забота UI.
                0
                Аналогично. Каждый компонент упакован в безопасный контейнер.

                С локализацией аналогичная проблема. Есть два способа передавать локаль в компоненты — или передать сразу ВСЮ локаль и дальше компонент уже сам по ключам найдет переводы или передавать только конкретные тексты в конкретных параметрах. Применяем и такой и такой подход, в зависимости от массивности компонента.
                0
                Скажите, а для рендеринга через rails, нужно ли делать экспорт компонентов в глобальный namespace? Если да, то какие инструмены для этого используете?
                  0
                  Нет, не нужно. Подключается скомпилированные на gulp-е js-файл со всеми компонентами.

                Only users with full accounts can post comments. Log in, please.