Всем привет, меня зовут Геворг. Я Head of Mobile в Profi.ru. Хочу поделиться с вами историей нашего эксперимента с React Native. Расскажу, как мы оценивали плюсы и минусы разработки на React Native — в теории и на практике. Статья будет полезна тем, кто интересуется кросс-платформенной мобильной разработкой, но пока не решил, идти в эту сторону или нет.

Максимальное ускорение



Всё началось с того, что мы решили ускорить разработку в 10 раз на уровне компании. Поставили невыполнимую цель, чтобы выйти за привычный горизонт событий и попробовать новое. Все команды разработки Profi.ru взялись за эксперименты. На тот момент в компании было 13 нативных мобильных разработчиков, включая меня и двух тимлидов. Моя команда работала над двумя мобильными приложениями. В первом клиенты ищут специалистов, во втором — специалисты клиентов. Для меня этот период был непонятным и эмоционально напряжённым. По моим ощущениям, мы и так много делали, чтобы всё работало быстро.

Использовали общую архитектуру на всём проекте и следили за чистотой кода. Использовали генераторы, которые создают все файлы модулей. Всю бизнес-логику старались выносить на backend. Настроили CI/CD, а приложения покрыли E2E-тестами. За счёт всего этого стабильно релизили некоторые приложения раз в неделю. Я понятия не имел, как ускорить разработку даже в два раза. Куда уж в 10. Поэтому мы определили, что для нас важно.

  1. Единая кодовая база. Хотелось, чтобы все наши мобильные разработчики писали один и тот же код. На одном языке, без платформенных отличий iOS и Android. Так мы могли ускорить разработку в два раза.
  2. Простота в освоении нового инструмента. Чтобы при расширении команды у нас не было проблем с переобучением или наймом.
  3. Быстрые релизы. Чтобы мы могли релизить не один раз в неделю, а каждый день.
  4. Моментальные обновления. Чтобы обновления получали все пользователи сразу. Как это сейчас происходит в веб-разработке.

После небольшого ресёрча появились три кандидата: React Native, Flutter, Kotlin/Native. Ни во Flutter, ни в Kotlin Native релизить быстро нельзя. А мы считали это едва ли не самым важным. Кроме того, эти технологии были совсем сырые на тот момент. Мы остановились на React Native — на нём можно релизить моментально. Плюс большая часть наших разработчиков уже использовала React.

Вообще я негативно относился к кросс-платформенным инструментам — как и большинство нативных мобильных разработчиков. Сходите на любую мобильную конференцию и поговорите об этом — вас сразу же закидают камнями. Сам люблю это дело :-) Поэтому, чтобы подтвердить или опровергнуть опасения, мы провели своё расследование.

Плюсы, риски и вопросы


Мы изучили примеры использования React Native в разных компаниях — удачные и не очень. С Head of Dev Борей Егоровым внимательно прочитали более трёх десятков статей и других материалов. В некоторых обсуждали каждый абзац. В конце статьи — ссылки на самые интересные. Мы отметили моменты, которые могут нас ускорить, возможные риски и вопросы. После этого пообщались с разработчиками из трёх компаний. В каждой ребята создавали массовый продукт и работали с React Native не меньше года.

С плюсами было всё довольно очевидно.

  1. Общая кодовая база.
  2. Over-the-Air, или обновление по воздуху, в обход сторов.
  3. Из первых двух пунктов следовало, что скорость доставки фич до пользователей вырастет.
  4. Веб-разработчики смогут писать код под мобильные приложения. Если веб-разработчик хорошо знает React, то он может быстро освоить React Native. А если мобильный разработчик уже знает эту платформу, то может относительно быстро войти в веб-разработку.

Список рисков был длиннее :-)

Риск первый. Вместо одной платформы мы в долгосрочной перспективе вынуждены поддерживать три: Android, iOS и React Native.

Иногда экран разработчика выглядит примерно вот так:



Реальность. Один из наших собеседников внедрял React Native в существующий код. Да, появляется полноценная третья платформа, но ты никуда не уходишь от нативной разработки. Его команде приходилось синхронизировать состояние между React Native и нативным кодом. Это влекло за собой много переключений между разными частями кода / разными парадигмами и IDE. Поэтому они решили написать новый проект с нуля, сделать каркас на React Native, а уже в него вставлять нативные куски там, где они нужны. Стало лучше.

Риск второй. React Native Black Box — иногда бывают ситуации, когда разработчик не понимает, из-за чего появился баг. Приходится искать везде: в React Native коде, в нативной части продукта или в самой платформе React Native.

Реальность. Ребята, с которыми мы общались, обкладывали приложение логами и разными инструментами: Crashlytics, Kibana и так далее. Проблемы остаются, но становится понятно, в каком месте они возникают.

Риск третий. В статьях часто встречалось, что React Native подходит для маленьких проектов, но не для больших продуктов с платформенной функциональностью.

Реальность. Мы посмотрели, есть ли на рынке большие компании, которые работают с React Native. Оказалось — их десятки, если не сотни. В том числе Skype, Tesla, Walmart, Uber Eats и «Кухня на районе».

Риск четвёртый. При каждом обновлении операционной системы от Apple или Google проект может сломаться.

Реальность. Решили, что риск вполне допустимый. Такой же риск есть и для нативной разработки. Когда выходит новая OS для iOS и Android, ты адаптируешь своё приложение под неё.

Риск пятый. Нет поддержки 64-битной системы в Android, причем issue открыто с 2015 года. А с августа 2019 года Google Play не принимает в сторы сборки, которые поддерживают только 32-битные системы.

Реальность. Мы посмотрели issue, над которым команда React Native работала летом 2018 года. Они обещали добавить поддержку в следующем релизе, хотя ещё не починили до конца поддержку 64-битной системы. Это сильно огорчало. Поддержку потом добавили, но некоторые Android-устройства падают после перехода. Как мы выяснили потом, процент мизерный, но всё равно это был самый болезненный для меня пункт.

Риск шестой. Вероятность, что завтра Apple или Google выпустят новую версию своей OS и сломают React Native. Или новую технологию, которую Profi.ru в принципе не сможет поддерживать.

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

Риск седьмой. Мы не могли сказать заранее, насколько React Native будет быстрым по сравнению с нативным приложением и какую производительность будет показывать.

Реальность. Дословная цитата одного из наших собеседников — «?списки элементов переменной высоты при скролле тормозили». Решили проверить на практике. Немного забегу вперёд — на момент написания первого прототипа приложения мы такой проблемы не увидели, но когда разрабатывали полноценное приложение, возникло множество вопросов по производительности React Native.

Риск восьмой. Непонятно, насколько быстро мы сможем найти разработчиков React Native. На HeadHunter я нашёл около 300 резюме, при том что разработчиков для iOS там было более 150 тысяч.

Реальность. Тут сильно углубляться не стали, так как уже не раз нанимали React-разработчиков и знали, на что обращать внимание. Решили, что в крайнем случае сможем переобучить React-разработчиков в React Native.

Ещё был риск, что кто-то уйдёт из команды, так как эту технологию мобильные разработчики недолюбливают. Кстати, я оказался прав. Кто-то ушел :-(

Я устал писать React Native, поэтому дальше будет просто RN :-)

Что меняем, а что нет


Мы обсудили результаты расследования с основателями компании Сергеем Кузнецовым и Егором Руди и получили добро на проведение эксперимента.

Решили создавать новый продукт с нуля, а не делать вставки в существующий. А ещё — не трогать наше клиентское приложение. Оно было довольно зрелым, и экономически не имело смысла что-то кардинально менять. Кроме того, нам было важно, чтобы в клиентском приложении был свой нативный опыт и для iOS, и для Android.

А вот приложение для специалистов мы хотели поменять радикально. В отличие от клиентского, нас не смущало, что у специалистов будет одинаковый опыт взаимодействия для приложений iOS и Android. Плюс мы считаем, что в продукте для специалистов можем обойтись без анимации и визуальных эффектов. Но прежде чем перейти всей командой на новую технологию, надо было пощупать, как она работает.

Эксперимент в действии




В декабре 2018 года мы собрали команду из трёх человек. Двух React-разработчиков и одного нативного — меня. Я понимаю, как работает Android, и хорошо разбираюсь в iOS-разработке.

В рамках эксперимента мы хотели проверить следующие пункты:

  • как работают мгновенные релизы в RN;
  • как идёт взаимодействие между нативными компонентами и RN;
  • сможем ли использовать наши нативные компоненты;
  • как RN работает с камерой, пушами и диплинками;
  • как работает навигация и сохранение состояния в RN;
  • насколько можем делать с RN pixel perfect;
  • как в RN работает автоматическое тестирование;
  • насколько быстро нативный или React-разработчик сможет изучить технологию.

Первые результаты мы получили уже через полтора месяца после погружения в разработку.

  • Я начал писать код под RN уже через две недели. Для меня технология оказалась совсем несложной. Мне очень помог один из наших React-разработчиков — он классно рассказал про React/Redux и JS в целом. Нужно было въехать в тонкости React/Redux, но через некоторое время «?нейронка начала обучаться», как говорят у нас в компании :-)
  • Я был приятно удивлён, что JS + Flow в каком-то виде дают строгую типизацию. По JS у меня были намного ниже ожидания. В то же время я точно отдал бы предпочтение Swift и Kotlin: они для меня в разы красивее и приятнее, чем JS, но тут главные слова «?для меня».
  • Нам помогло, что в команде были разработчики, которые умеют писать код и для iOS, и для Android, и для React. В каждой из платформ появлялись свои специфические проблемы. Чтобы их решать, команда должна быть кросс-функциональной.
  • Мгновенные релизы работают. Для меня это как магия. Не надо ждать релизов и апрувов от Apple. Захотел — взял и выпустил.
  • Очень часто проект ломался. Это реально не круто. Ты взял изменения с ветки, пробуешь запустить — и ни фига. Это сильно раздражало. В какой-то момент мы просто написали скрипт, который чистит проект полностью. Нельзя сказать, что решили проблему целиком, но большую часть добили.
  • Всё равно приходится работать с тремя платформами, несмотря на то, что мы в основном пишем код на RN. У всех разработчиков стояли три IDE: Xcode, Android Studio, WebStorm.
  • Пуши, диплинки, камера, навигация заводятся. Но заводятся либо с помощью сторонних библиотек, либо библиотеки в нативном коде надо писать самому, а потом подключать в RN.

В конце статьи хочется вернуться к заголовку. Так является ли RN серебряной пулей для всех проблем? Мы для себя решили, что нет. В то же время получили, что хотели. Мы увеличили в несколько раз скорость доставки фич и теперь можем релизить на всех пользователей каждый день. Также важно, что в компании появились кросс-функциональные команды, где каждый разработчик пишет код, как в Android/iOS, так и в вебе.

И да, приложения в сторах :-)

Полезные статьи про React Native


  1. Why Discord is Sticking with React Native — Fanghao (Robin) Chen
  2. Как я полюбил и возненавидел React Native — Андрей Мелихов
  3. React Native с точки зрения мобильного разработчика — Андрей Константинов
  4. React Native at Instagram — Instagram Engineering
  5. React Native: A retrospective from the mobile-engineering team at Udacity — Nate Ebel
  6. React Native: батл по фактам в одном действии — Samat Galimov
  7. Sunsetting React Native — Gabriel Peal

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


  1. SayLovePlz
    28.11.2019 11:42

    Спасибо за статью!

    Очень часто проект ломался. Это реально не круто. Ты взял изменения с ветки, пробуешь запустить — и ни фига. Это сильно раздражало. В какой-то момент мы просто написали скрипт, который чистит проект полностью. Нельзя сказать, что решили проблему целиком, но большую часть добили.

    Можете рассказать про этот скрипт подробнее?


    1. gev_petrosian Автор
      30.11.2019 11:00

      Добрый день. Как я писал уже выше, скрипт очень простой, он просто чистит проект


      В package.json
      `
      "scripts": {

      "reinstalldeps": "rm -rf node_modules && yarn && yarn jetify && cd ios && pod install && cd ../"

      }


  1. Vasily_T
    28.11.2019 11:57

    Давно хотел попробовать RN, вот пожалуй после этой статьи хотя бы для теста что нибудь напишу,
    спасибо за Ваш experience!


  1. Izulle
    28.11.2019 12:24

    Мгновенные релизы не входят в противоречие с политикой  AppStore?


    1. mrTyler
      28.11.2019 12:56

      в данный момент Apple закрывает на это глаза и позволяет совершать code-push в уже имеющиеся приложения. 3 года так делаем — полет нормальный.


  1. Gorniv
    28.11.2019 12:38

    Реальность. Мы посмотрели, есть ли на рынке большие компании, которые работают с React Native. Оказалось — их десятки, если не сотни. В том числе Skype, Tesla, Walmart, Uber Eats и «Кухня на районе».

    Теперь стало понятно почему «Кухня на районе» не запускалась на моем старом Android…


  1. Cobalt
    28.11.2019 17:28

    С React Native есть одна большая проблема. Если вы написали проект, опубликовали, пол года — год его не трогали (занимаясь в это время новыми на том же RN), а потом вам понадобилось что-то обновить и допилить — это боль. Нет, это БОЛЬ! Просто запустить «старый» проект не получится. С того времени обновились как сами нативные платформы, так и React с React Native, что приводит к тому, что старый код в новом окружении просто отказывается заводится. Сначала пытаешься обновить все нативные либы до актуальных, потом берешься за js либы… Иногда и 8 часов на запуск не хватает. Если проект не большой, то бывает гораздо проще создать с нуля голый React Native проект и перетянуть в него код из старого — только это дает хоть какую-то гарантию запуска (((


    1. mrTyler
      29.11.2019 09:22

      увы да, особенно это было великолепно на стыке RN 0.59 с 0.60 и одновременным обновлением до Xcode 11, в котором они изменили несколько нативных методов. Вы просто не могли запустить RN0.59 на Xcode11, и хотя потом вышла заплатка для RN, вы все равно сделать бы это не смогли XD


  1. bugdesigner
    29.11.2019 07:55

    Намного интереснее было бы прочитать статью о том, как ускорить работу приложения в 10 раз. У вас же главное — как можно скорее выпустить приложение. Качество съедено количеством?


    1. sc_pro_ion
      29.11.2019 10:34

      Сейчас мы взяли вектор на качество, поэтому активно занимаемся ускорением. Готовлю статью на эту тему, скоро появится на хабре.


  1. beduin01
    29.11.2019 08:53

    Почему Dart/Flutter то не взяли? В нем описанных проблем нет как класса.


    Есть конечно свои проблемы, но они не столь болезненные как описанные в статье.


    1. gev_petrosian Автор
      30.11.2019 11:13

      Как я писал выше, для нас важны были следующие пункты:


      1. Быстрые релизы. Чтобы мы могли релизить не один раз в неделю, а каждый день.
      2. Моментальные обновления. Чтобы обновления получали все пользователи сразу. Как это сейчас происходит в веб-разработке.

      Я не знаю как сейчас, но на тот момент, когда мы выбирали инструмент, мы не нашли способа быстрых релизов во Dart/Flutter-е.