React Native и Flutter позволяют написать одно приложение сразу для iOS и Android. Оба зрелые и подходят для большинства бизнес-приложений, но устроены по-разному, и от этого зависят интерфейс, найм и стоимость поддержки. Я пишу на React Native и нативно на Swift и Kotlin; Flutter разбираю как сторонний обзор по документации.
| Критерий | React Native | Flutter |
|---|---|---|
| Порог входа | JavaScript или TypeScript и React. Веб-разработчик начинает быстро. | Язык Dart и своя система виджетов. Язык простой, но его учат отдельно. |
| Экосистема | npm, Expo и библиотеки из веба для логики. Качество нативных библиотек разное. | pub.dev и большой набор официальных виджетов. Интерфейс собирается почти без сторонних пакетов. |
| Производительность и UX | Системные компоненты платформы, приложение выглядит привычно для iOS и Android. | Собственный движок отрисовки. Одинаковый вид на всех платформах и плавная анимация. |
| Типовые задачи | Продукт с сайтом на React, общая логика с вебом, быстрые правки JS-кода. | Приложение со сложным фирменным дизайном, один интерфейс на мобильных и десктопе. |
| Найм и поддержка | Большой рынок JS-разработчиков, людей можно делить с веб-командой. | Нужны отдельные специалисты по Dart. Фреймворк и основные виджеты развивает одна команда. |
React Native развивает Meta, Flutter развивает Google. Оба проекта открытые и бесплатные.
React Native устроен как React для мобильных. Компоненты, хуки и состояние работают так же, как в вебе. Меняются базовые элементы: вместо div и span используются View и Text, а стили задаются объектами. Фронтендер на React быстро начинает писать экраны.
Для старта удобно взять Expo. Документация React Native советует начинать новый проект с фреймворка, и Expo там основной вариант.
Flutter использует язык Dart. У Dart строгая типизация и привычный синтаксис, поэтому разработчику с опытом Java, Kotlin или TypeScript он даётся легко. Интерфейс собирается из виджетов: отступ, кнопка и целый экран тоже виджеты. Для веб-разработчика такой подход новый.
Сложности у обоих начинаются на стыке с платформой. Нужно разбираться в сборке под iOS и Android, правах доступа, push-уведомлениях и публикации в магазинах.
React Native берёт пакеты из npm. Валидацию, работу с датами и API-клиенты можно использовать те же, что в вебе. Модули для камеры, Bluetooth или фоновых задач часто пишут сторонние авторы, и качество у них разное. Expo закрывает многие типовые функции своими модулями и даёт облачную сборку через EAS Build.
У Flutter пакеты лежат на pub.dev. Сильная сторона Flutter в большом наборе официальных виджетов в стилях Material и Cupertino. Доступ к функциям устройства тоже идёт через плагины: часть поддерживает команда Flutter, остальные сторонние.
Если нужной функции нет, оба фреймворка дают выход в нативный код. В React Native пишут нативный модуль. Во Flutter используют платформенные каналы или FFI. Для React Native такие модули я пишу на Swift и Kotlin.
React Native показывает настоящие компоненты платформы. Поля ввода и прокрутка ведут себя так, как привык пользователь iOS или Android. JavaScript выполняется в движке Hermes. В новой архитектуре он обращается к нативному слою напрямую через JSI, без старого асинхронного моста. Для сложных анимаций берут Reanimated: он выполняет анимацию в потоке интерфейса.
Flutter рисует интерфейс сам, своим движком. Код на Dart в релизной сборке компилируется в машинный код. Отсюда одинаковый вид на всех платформах и предсказуемая плавность. Обратная сторона в том, что системные элементы Flutter повторяет своими виджетами. Когда Apple или Google меняют системный дизайн, приложение на Flutter получает его после обновления фреймворка.
Оба фреймворка добавляют в приложение свой движок, поэтому сборка весит больше нативной. Для игр и тяжёлой 3D-графики лучше подходят игровые движки или нативный код.
Типичные задачи для обоих одинаковые: магазин, доставка, запись на услуги, личный кабинет, внутреннее приложение для сотрудников. Разница видна в окружении проекта.
React Native хорош, когда у компании уже есть сайт или кабинет на React. Типы, API-клиент, валидация и часть бизнес-логики становятся общими. Ещё один плюс: JS-часть приложения можно обновлять без новой сборки через EAS Update, если правка укладывается в правила App Store и Google Play.
Flutter хорош для приложений с фирменным дизайном, который должен одинаково выглядеть на всех устройствах. Его выбирают и тогда, когда нужно одно приложение для телефонов и десктопа.
Разработчиков на JavaScript и TypeScript на рынке много, и многие из них знают React. Поэтому для React Native проще найти человека и можно делить задачи с веб-командой. Разработчика на Flutter ищут отдельно: Dart почти не используется вне Flutter.
Поддержка мобильного приложения стоит денег при любом выборе. Каждый год выходят новые версии iOS и Android, магазины поднимают требования к сборке, и приложение приходится пересобирать и проверять. В React Native многое зависит от сторонних нативных библиотек. Если автор перестал их обновлять, библиотеку меняют или чинят сами. Expo снижает эту нагрузку, потому что выпускает согласованные наборы модулей.
У Flutter больше функций в самом фреймворке, но плагины для доступа к устройству тоже приходится обновлять.
Отдельное приложение под каждую платформу. Полный доступ к API системы с первого дня, лучшая производительность и привычный интерфейс. Цена в том, что кодовых баз две, и каждую функцию делают дважды.
Одна кодовая база для iOS и Android, одна команда и общий релизный цикл. Нативный код нужен точечно, для функций, которых нет в фреймворке.
Сайт, который ставится на экран телефона, работает без сети через service worker и обновляется без магазинов. Ревью нет, один код работает везде, где есть браузер.
Нативный путь оправдан, когда приложение глубоко работает с системой: обработка видео и звука, AR, сложная работа с Bluetooth и фоновыми задачами, приложения для часов. Часть нативного кода нужна и в кроссплатформенном приложении. Например, виджеты для экрана «Домой» на iOS пишутся на SwiftUI. Есть и промежуточный вариант: Kotlin Multiplatform выносит общую логику в Kotlin и оставляет нативный интерфейс на каждой платформе.
У PWA ограничения заметнее всего на iOS. Веб-push там приходит только в PWA, добавленную на экран «Домой», а Web Bluetooth и Web NFC в Safari нет. Чтобы попасть в App Store и Google Play, PWA заворачивают в нативную оболочку, и тогда на неё распространяются правила ревью.
PWA подходит для MVP, внутренних инструментов и сервисов, которыми и так пользуются из браузера. Если аудитория живёт в Telegram, вместо отдельного приложения иногда хватает Mini App.
Telegram Mini Apps →Общий язык, типы и API-клиент. Одна команда ведёт и сайт, и приложение.
Приложение использует системные компоненты и выглядит своим и на iOS, и на Android.
Изменения в JS-коде доставляют через EAS Update без новой сборки, если они укладываются в правила магазинов.
Разработчиков на JavaScript и TypeScript много, людей проще найти и заменить.
Собственный движок отрисовки даёт одинаковый до пикселя интерфейс на всех устройствах.
Flutter официально поддерживает iOS, Android, веб, Windows, macOS и Linux.
Если проект начинается с нуля, плюс общего кода с сайтом пропадает, и выбор упирается в людей.
Опыт команды важнее разницы между фреймворками.
Если у вас есть веб на React или команда на TypeScript, берите React Native. Если важен единый фирменный интерфейс на многих платформах и есть люди с Dart, берите Flutter. Нативную разработку на Swift и Kotlin выбирайте, когда приложение глубоко работает с железом и системой. PWA подойдёт, чтобы проверить идею без магазинов и ревью.
В типовом приложении с формами, списками и карточками пользователь разницы не заметит. Flutter рисует интерфейс своим движком и даёт предсказуемую плавность. React Native показывает системные компоненты, а тяжёлые анимации выполняет в потоке интерфейса через Reanimated.
Частично. С React Native общими с сайтом на React становятся логика, типы и API-клиент, а экраны обычно делают отдельно. Flutter умеет собирать веб-версию, но для контентного сайта с SEO она подходит плохо.
Когда приложение глубоко работает с системой: обработка видео и звука, AR, Bluetooth, фоновые задачи, приложения для часов. В остальных случаях кроссплатформа обходится дешевле, а отдельные нативные модули к ней дописывают на Swift и Kotlin.
Да, это нормальный путь для проверки идеи. PWA ставится на экран телефона и работает без магазинов. Когда понадобятся функции устройства, которых нет в браузере, или присутствие в App Store и Google Play, приложение делают на React Native или Flutter. Серверная часть при этом остаётся прежней.
Зависит от команды. Если у вас уже есть веб-разработчики на React, React Native обойдётся дешевле за счёт общего кода и людей. В обоих случаях бюджет на поддержку нужен постоянно: новые версии iOS и Android и требования магазинов заставляют регулярно обновлять приложение.
Напишите в Telegram, что должно делать приложение и есть ли у вас сайт или бэкенд. Подскажу, какой путь подойдёт: кроссплатформа, натив или PWA.