Логотип компании Goodbit

Flutter vs React-Native: детальное сравнение

Евгений

Евгений

Руководитель DevOps Отдела

Flutter vs React Native

Flutter — это технология, которая в настоящее время вызывает ажиотаж в мобильной разработке. Его стали чаще выбирать для создания новых приложений, а некоторые разработчики переписывают на Flutter даже старые приложения, по сути, без каких-то видимых на то причин.


Я провел с Flutter несколько месяцев на продакшн проекте, и хочу поделиться опытом, сравнив его с React-Native, с которым у меня довольно богатый опыт.


Я хотел бы подробно остановиться на том, что, что вам нужно учитывать, если вы переходите на кроссплатформенный нативный подход, и хотите понять, что вам больше всего подходит — Flutter или React-Native.


Обычно у вас есть 3 варианта мобильного приложения: полностью родное с Kotlin / Swift, полностью веб-приложение (PWA или контейнер WebView) и что-то среднее. Мы называем этот вариант Cross Platform Native, поскольку это не веб-приложения, а Native Apps, которые тем не менее используют кроссплатформенный подход.


Обе технологии предоставляют схожие возможности, однако использовать Flutter немного рискованно сейчас из-за его незрелости, недостатка библиотек и не очень большого пока ещё сообщества.

Критерии оценки

Я не буду углубляться в суть технологий, а оценю их с точки зрения применения в проектах и их возможностей в целом. Я рассмотрел следующие аспекты:


  1. Сборка и развертывание.
  2. Доступность библиотек и виджетов.
  3. Инструменты и тестирование.
  4. Производительность.
  5. Опыт разработчиков.
  6. Возможности сети.
  7. Возможности медиа.
  8. Безопасность.
Рейтинг

Сборка и развертывание

Обе технологии — кроссплатформенные и используют один и тот же подход: у них есть собственные части для Android и iOS, и включают кроссплатформенные среды выполнения, будь то JavaScript или Dart. Это можно представить следующим образом:

Блок схема работы работы кроссплатформенных приложений

Сборка

Обе платформы используют инструменты мобильной операционной системы для сборки: Gradle и Xcode build для Android и iOS соответственно. В этом плане разницы между ними и нативными приложениями нет.


Хотя есть разница в скорости сборки. Это не так важно для разработки, однако критично во время сборки CI и архивирования приложения в Xcode. У меня нет точных цифр, но у меня приложение «Hello, World» на Flutter собирается мерно в 3 раза быстрее, чем в React Native. Причина в том, что Flutter поставляется как iOS Framework, а React Native перекомпилируется из исходников.

Публикация

Описанная выше архитектура означает, что необходимо преобразовать или скомпилировать общий код, включить его в окончательный apk / ipa и отправить результат в магазин приложений. Процесс может выглядеть следующим образом:


Процесс публикации приложения

Однако между RN и Flutter всё же есть различия.


React Native поддерживает технологию Code Push, позволяющую отправлять обновления кода JS без повторной публикации apk / ipa из-за того, что React Native запускает пакет кода JS во время выполнения и может его заменить.


По сути, это можно считать некой проблемой безопасности. Команда Flutter, приняв это во внимание, вообще решили не поддерживать эту функцию.

Производительность

Производительность следует рассматривать с нескольких точек зрения:


  • Производительность рендеринга
  • Собственное взаимодействие
  • Время запуска

Производительность рендеринга

React Native использует родные виджеты платформы(Native Views) и передает события через JavaScript. Это влияет на производительность уровня представления, однако 60 fps в секунду все еще достижимы, хотя производительность зависит от версии ОС и самого устройства.

Flutter, с другой стороны, рендерит все, используя собственный 2D-движок Skia, избегая какого-либо специального соединения между вьюшками и другим кодом. Это делает рендеринг невероятно быстрым. У него могут быть проблемы с iOS, но эта проблема должна быть решена с помощью недавней поддержки Metal.

Взаимодействие с платформой

Сейчас я ничего не могу сказать, так как для этого требуется микробенчмаркинг обоих решений на разных устройствах. Это тема для отдельной статьи.

Время запуска

У React Native есть проблема с этим. Вообще, время запуска — это распространенная проблема, если вы стремитесь к совершенству своего мобильного приложения. RN должен загрузить виртуальную машину JS, а затем JS код. На Android это становится сложной задачей. Версия React-Native 0.60 обеспечивает поддержку Hermes: новой экспериментальной виртуальной машины JS для Android, которая предназначена для быстрой загрузки.


Flutter, кажется, уже решил эту проблему.

Сетевые возможности

React Native работает с базовым протоколом http(s) с полифилом fetch, встроенной поддержкой WebSockets и богатые клиенты с axios (еще один пример чистой библиотеки js!) и rn-fetch-blob. React Native также парсит json из коробки, потому что это тоже JavaScript. Это также означает, что можно создавать свои типы с помощью Open Api.


У Flutter есть только встроенные клиенты http (s) и WebSockets. Клиент Axios находится в стадии разработки (я даже думаю о создании собственного, скажем, «fluxios»)). Парсинг JSON(конечно, если вы не используете кодогенерацию) нужно производить вручную. Поддержка открытого API существует, но она не обновлялась 15 месяцев. Существуют пакеты Dio и Chopper для упрощения работы с http, и скорее всего, появятся еще.


К сожалению, как оказалось, использование кодогенерации для openapi для Dart вызывает определенные проблемы, прочитать про которые можно тут.

Безопасность

React Native завязан на js и приложение на его основе содержит js bundle. Но его всегда можно извлечь и понять логику приложения, или изменить ее. Похоже, это серьезная проблема.


С Flutter гораздо сложнее изменить приложение, так как Dart код заранее компилируется в бинарный код для целевой архитектуры.

Управление зависимостями

React Native использует пакеты NPM для включения зависимостей приложения, включая сам React Native. Помимо NPM, можно использовать Yarn для установки и управления своими зависимостями. Зависимости, которые требуют кода Kotlin / Java / Swift / Objective-C, связываются с помощью модулей gradle и пакетов CocoaPods. React Native включает функцию автоматической линковки, которая позволяет избежать ручного изменения файлов gradle и Podfile.


Flutter, в свою очередь, использует менеджер пакетов dart, также известный как инструмент pub. Пакеты поставляются в виде исходного кода и компилируются вместе с основным приложением. Как и в RN, эти пакеты могут иметь собственные зависимости, но в этом случае может потребоваться вручную добавить эти зависимости в файлы gradle и Podspec, хотя на практике лично я с этим не сталкивался. Можно также использовать неопубликованные пакеты, забирая их из папки или git репозитория.

Виджеты

React-Native имеет большую библиотеку компонентов пользовательского интерфейса: календари, средства выбора даты, кнопки, компоненты материалов, поддержку SVG и многое другое.


Flutter поставляется с компонентами Material и Cupertino из коробки. Но вот библиотека пользовательского интерфейса находится на ранней стадии. Возможно, с недостатком компонентов вы и не столкнетесь, однако количество библиотек компонентов для React Native намного больше. Это изменится в ближайшем будущем, поскольку все больше и больше разработчиков работают с Flutters.

Инструменты и тестирование

Мне кажется, что в этом обе примерно технологии равны. Оба стека включают:


  • Инструменты стиля и качества кода (eslint, tslint, prettier vs dartanalyzer).
  • Unit-тесты (с Jest-тестом и Flutter-тестом).
  • Тесты компонентов (снимки, Enzyme-тесты и виджет-тесты, «золотые тесты»).
  • e2e тестирование (Detox vs e2e).

Опыт разработчика (DX, Developer Experience)

У React Native есть функция Fast Refresh, которая позволяет мгновенно видеть изменения на симуляторе / эмуляторе или реальном устройстве, это сокращает цикл обратной связи практически до нуля, в отличие от нативной разработки. Разработка обычно выполняется с помощью VSCode или WebStorm (это самые популярные инструменты). Оба включают в себя возможности для запуска и отладки кода, запуска тестов, просмотра покрытия и обеспечения автозаполнения. На мой взгляд у RN автозаполнение ограничено (я думаю, из-за JavaScript), поэтому я вернулся к запуску сборки либо с npx react-native run-ios или через Xcode, потому что запуск через WebStorm был очень нестабильным. Также время от времени падал сам упаковщик. Типичный способ отладки — это запуск Google Chrome и использование его консоли, что является неоптимальным.


У Flutter отличный DX. Поскольку это продукт Google, он позволяет интегрировать IDE (Android Studio, но я предпочитаю IntelliJ Idea как более стабильную) сразу с набором инструментов. Быстрая загрузка почти такая же, как и быстрое обновление, и даже лучше. Автозаполнение работает на ура, поскольку Dart строго статический и типизированный, что создает поддержку стабильности среды разработки IDE. Тут надо сделать замечание, что Dart из коробки предоставляет большую свободу в плане типов, вы можете их вообще не писать, поэтому рекомендуется его донастроить в своем проекте.


Кроме того Flutter показывает причины ошибок, поэтому их легко пофиксить. Отладчик в IDE тоже работает очень хорошо. VSCode также поддерживает Flutter, но не имеет функций отладки и VCS.


Код Dart

Медиавозможности

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


React Native поддерживает воспроизведение и запись как аудио, так и видео. Можно, например, показывать видео в разных форматах (в основном все они поддерживаются ExoPlayer (Android) и AVPlayer (iOS)), отображать элементы управления для поиска, зацикливания и т.д. Также можно отображать субтитры SRT и VTT для видео «из коробки». Этот функционал поставляется с такими компонентами, как react-native-video,react-native-video-controls и другими.


В основном Flutter имеет только пакет video_player для воспроизведения видео. Его версия 1.0 все еще находится на рассмотрении и может отображать все видеоформаты, предоставляемые мобильными ОС, а вот субтитры — только SRT, субтитры VTT отсутствуют в дорожной карте. VTT субтитры тем не менее поддерживается отдельным пакетом. Для основных элементов управления необходимо использовать пакет Chewie.

Вывод

Как всегда, выбор зависит от нефункциональных требований, но я бы рекомендовал при этом учитывать:


  1. Недостаток библиотек для Flutter.
  2. Обучение Dart новым разработчикам, так как таких разработчиков на рынке нет/мало.
  3. Неполные медиа возможности для Flutter.
  4. Более длительное время запуска React-Native.
  5. Более низкая безопасность для React-Native.
Три человечка смотрят на to-do list