React Native: мифы, претензии и реальные проблемы
Привет, Хабр! Меня зовут Кирилл, я ведущий разработчик в Lad. В статье, опираясь на мой реальный опыт, хочу развеять все мифы о React Native, которые накопились, и рассказать, на что способен этот кроссплатформенный фреймворк.
Основные мифы и претензии к React Native
В этой главе, я попытался собрать основные претензии к React Native, чтобы их опровергнуть)
Низкая скорость старта
Это ненативно
Performance — мало fps, все лагает
Ничего большого на этом не построишь
Вы не фронты и не мобильщики
Низкая скорость старта
Очень много видео было в начале зарождения React Native и там действительно были проблемы. Раньше React Native подгружал в память все модули приложения при его старте, что давало долгий запуск приложения.
В дополнение к этому частенько сравнивали React Native Expo с миллионом всяких встроенных модулей и нативный Hello world с 0 зависимостей: D
В новых версиях RN модули подгружаются по мере необходимости)
А теперь сравним более справедливо с новой версией.
Соберем для android production сборки Hello world для native android и init для React Native CLI — оба сбилжены через команду assembleRelease и установлены на 1 и тот же симулятор android
Визуально разница практически не заметна, а если посмотреть logcat, то там можно увидеть:
558–576 ActivityTaskManager system_server I Displayed com.example.androidcompare/.MainActivity for user 0: +306ms
558–576 ActivityTaskManager system_server I Displayed com.awesomeproject/.MainActivity for user 0: +179ms
Это ненативно
Совсем недавно в открытый доступ вышел хороший доклад как раз на эту тему, где все доступно рассказано)
Если хочется углубиться можно почитать внутреннее устройство архитектуры.
Прочитав это, можно убедиться, что каждый компонент объявленный внутри RN на стороне js/ts — по факту является ссылкой на нативный компонент. Только мы все равно никому не доверяем и хотим убедиться сами в этом: D
Проверим: React Native на Android
Посмотрим через Layout Inspector на нулевое приложение написанное на RN. Тут в иерархии видно, что View на стороне js конвертируется в ReactViewGroup для android
Поглядим что это за ReactTextGroup и увидим, что он наследуется от нативного android класса ViewGroup
Проверим: React Native на iOS
Посмотрим через Layout Inspector на такое же нулевое приложение написанное на RN. Тут в иерархии видно, что View на стороне js конвертируется в RCTView, который наследуется от UIView из UIKit
Performance — мало fps, все лагает
Как и в любой технологии, тут все очень сильно зависит от программистов. Медленный и неоптимизированный код можно написать на чем угодно. Во всех наших приложениях стабильные 60 fps. Если в вашем приложении fps проседает, возможно, самое время углубиться в литературу по оптимизации:)
Ничего большого на React Native не построишь
Крайне сомнительно: c
У нас есть кейсы:
Вы не фронты и не мобильщики
А кто мы если так подумать? Мы и не фронты, хотя можем во фронтенд… Мы и не мобильщики, хотя можем писать нативщину и с ней интегрироваться…
Путь тогда мы будем китами в океане программирования: D
Реальные проблемы React Native
Мой кейс разработки приложения на React Native для iOS и Android
На одном из наших больших проектов (~200 экранов) бизнесу заказчика очень нужно было пилить фичи «non-stop». Нас связывали по рукам и ногам, не давая возможности на какой-то рефакторинг/обновление либ и тд. В один прекрасный день мы смогли убедить его, что пора бы обновить RN, чтобы получить все новые крутые фичи, которые ускорили бы разработку… И вот что из этого вышло.
> ВЫ ЧТО ТАКОЕ СДЕЛАЛИ ОТКУДА ТАК МНОГО?
React Native 0.60.6 → 0.65.1
Само по себе обновление RN не такое страшное, гораздо страшнее его последствия.
Что нам пришлось пережить, можно смотреть в старом changelog. Я лишь приведу один пример с picker-ом
Раньше он жил внутри RN (iOS и Android), потом он ушел в @react-native-community/picker, затем перекочевал в react-native-picker/picker. API у каждой либы чутка менялся.
Естественно, кол-во ченджей в нашем мр будет расти с каждым подобным компонентом, который не работает в новой версии: c
Чтобы заставить приложение собраться и запуститься, ушло ~50–100 changes
А также новая версия RN требовала новый React и новую навигацию…
React 16.13.1 → 17.02
Это как раз то изменение, где поменяли работу с жизненными циклами в React. Некоторые наши и open-source компоненты были завязаны на эти старые циклы.
Наш changelog растет ещё на ~30–50 changes
react-navigation → @react-navigation/native
Ух, это было больно… Старая версия навигации не работала с новой версией RN. Ребята полностью сломали обратную совместимость — работа с либой поменялась кардинально.
Это была долгая, муторная и монотонная работа переезда с одного API на другое
(Вы же помните, что тут ~200 экранов?)
Все остальные изменения были из-за этого переезда ~411–508 changes!
Выводы
Обновляйтесь своевременно
Договаривайтесь с бизнесом заранее
Делайте «обертки» над компонентами, которыми строите ваше приложение
Используете современные подходы как FSD
Послесловие
Справедливости ради сейчас команды React Native и @react-navigation/native крайне аккуратно и плавно развивают проекты. С такой ситуацией столкнулись только на одном этом проекте 2 года назад, и больше такого нигде не было
Но ведь это все не зря?
Скорость разработки +100500
В качестве примера можно привести недавний короткий проект, который длился 13 спринтов по 2 недели каждый
Что было сделано за это небольшое время:
Аутентификация
Авторизация
Регистрация
Восстановление пароля
Профиль пользователя
Возможность удалить профиль
Аватарки
И другая информация о пользователе
Интеграция с Android Health Connect и Apple HealthKit
Выводим данные по сну
Рисуем графики по расходу энергии
Сервис «Товары»
Список товаров
Корзина
Оформление заказов
История заказов
Рейтинг товаров
Сервис «Моя фигура и цели»
Графики для отображение динамики веса
Установка целей пользователем
Сервис «Питание»
Список преднаполненных блюд
Создание своих блюд
Рисование анимированных графиков по целям и калориям
Трекинг что ел на завтрак/обед/ужин
Трекинг выпитой воды
Сервис «Тренировки»
Создание/редактирование программы тренировки
Создание/редактирование плана тренировки
Создание/редактирование упражнения
Выполнение тренировок
История тренировок
Сервис «Здоровье»
Возможность проходить опросы
Загрузка и парсинг результатов обследований
Трекинг Биоимпеданс-а с графиками
Сервис «Мои специалисты»
Возможность выбрать пользователю специалиста
Сервис «Клиенты»
Возможность специалисту смотреть информацию о клиенте
Лента клиента, которая включает в себя группировку всех действий клиента в приложении
Сервис «Рекомендации»
Специалист может назначать рекомендацию на клиента
Сервис «Календарь привычек»
Отслеживать выполнение хороших или не выполнение плохих привычек с отчетом сколько дней пользователь держится
Сервис «Видеозвонки»
Специалист и клиент могут создавать созвоны между собой
Клиент и специалист может созваниваться прямо в приложении и обсудить что-то с глазу на глаз
Ну и, естественно, там есть возможность мульти темы благодаря нашей open-source UI либы mobydick, мультиязычность с помощью i18next, и вероятно, я забыл что-то ещё упомянуть: D
А что по команде? Большинство спринтов был один разраб на постоянку и одного подключали периодически по необходимости на полспринта.
Как итог — получаем приложение для iOS и Android за ~ 6 месяцев.
1 язык (3+ языка)
Разработчика, знающего React, найти очень просто на рынке труда. Переезд с React на React Native крайне легок и быстр. И этот один разработчик закроет 95% ваших бизнес-хотелок на Android и iOS, используя только js/ts!
Рано или поздно настанет время, и ему попадется что-то, чего нет в open-source, а может, и не настанет:)
В любом случае React Native не забирает у вас возможность писать Native Module для определенной платформы. Если чего-то нет (что маловероятно) — просто напиши это:)
И там уже можно использовать для Android/iOS — Kotlin/Swift или Java/Objective-C
Если и этого мало — там же можно линковать любой low-level язык (С, C++, Rust)
Что можно сделать на React Native?
Это можно посмотреть самостоятельно в showcase, мне лишь хочется выделить 1 игру/приложение, которая там не фигурирует — Voidpet garden
Долгое время висело в топ App Store
Номинирован на приложение года в google play
Под капотом используется Skia для всей 2d анимированной графики
Выглядит красиво, работает плавно — людям нравится)
(Это приложение на обе платформы сделал 1 программист)
Коротко про альтернативы React Native
Flutter
Главный конкурент React Native, за которым стоит Google
Плюсы
Хорошо оптимизирован
За него вписался Google
Минусы (сомнительные и натянутые)
Мимикрирует под нативные компоненты
По факту использует движок рендера, который не использует встроенные в платформу компоненты. Что опять же не то чтобы плохо, только иногда порождает забавное поведениеИспользуется Dart
Хороший язык, был долгое время на хайпе. Сейчас не слышал, чтобы он использовался помимо Flutter
(Возможно, его просто нет в моем информационном пузыре: c)
Native Script
Его я щупал меньше всего, все же упомянуть его стоит)
Плюсы
Является OpenJS Foundation
Дает прямой доступ к платформам API
Минусы (сомнительные и натянутые)
Чуть меньше комьюнити по сравнению с другими технологиями
Layout описывается XML (Это, вероятно, вкусовщина)
Нативное приложение
Плюсы
Точно нативно
Работать будет хорошо, при наличии хорошей команды
Все фичи платформ доступны
Минусы
Как минимум нужны 2 команды на iOS и Android
Скорость разработки
Что посмотреть
Хороший разбор мифов по RN — Ислам Рустамов — Внутреннее устройство React Native
Создатель Voidpet Garden — After 13 months of building a Website, I switched to an App
The Ultimate Guide to React Native Optimization — https://www.callstack.com/ebook/the-ultimate-guide-to-react-native-optimization