Перейти к содержимому
syncra
Все заметки

React Native: от создания проекта до App Store и Google Play

Написание самого приложения планируют все. А сроки запуска срываются на подписании, тестовых треках, формах о приватности и ревью в магазинах. Вот путь, которым я иду от пустого репозитория до обоих магазинов.

Автор: , основатель6 мин чтения

Я делаю приложения на React и React Native больше семи лет и провёл несколько из них через ревью App Store и Google Play. Среди них — мобильное банковское приложение для Молдовы с интеграциями MAIB и MPass и подписками через RevenueCat, а также приложение для знакомств; оба я делал как сотрудник или подрядчик компаний, которым они принадлежат. В Syncra мы сейчас делаем собственное мобильное приложение — iBeep. Оно ещё в разработке, и в магазинах его пока нет.

Запуск редко задерживает код. Его задерживает всё, что вокруг кода: подписание, тестовые треки, декларации о приватности, ревью и первое обновление после релиза. Ниже — путь, которым я иду, по порядку.

1. Начните с Expo и рано переходите на development builds

Для нового приложения на React Native я по умолчанию беру Expo. Документация React Native сама рекомендует начинать с фреймворка, и Expo — тот, которым пользуется большинство команд. Он даёт разумную структуру проекта, файловый роутинг, большой набор поддерживаемых нативных модулей и сервис сборки.

На старте важны два решения:

  • Используйте development builds, а не Expo Go, как только добавляете нативный модуль, которого нет в Expo Go. Development build — это ваше собственное приложение с меню разработчика, и там, где это важно, оно ведёт себя как продакшен-версия.
  • Пусть нативные проекты генерирует Expo. С prebuild папки ios и android генерируются из конфигурации приложения, а нативные изменения проходят через config plugins. Обновление превращается в правку конфига, а не в конфликт слияния в проекте Xcode.

Полностью переходить на bare-проект приходится редко. Собственный нативный код всё равно вписывается — в виде модуля Expo или локального config plugin.

2. Стройте репозиторий в расчёте на несколько приложений

Мобильное приложение редко живёт само по себе. Есть API, админка, часто лендинг. Когда всё это лежит в одном монорепозитории, у них могут быть общие типы, схемы валидации и константы, а изменение контракта API проявляется как ошибка типов в приложении, а не как падение в продакшене.

iBeep устроен именно так: монорепозиторий на Turborepo, где рядом лежат приложение на Expo, API и лендинг. Держите границы чёткими. В общих пакетах — типы и чистая логика и никогда не код React Native, который пришлось бы устанавливать серверу.

3. Разделите окружения с первого дня

Настройте три варианта до того, как они понадобятся: development, preview и production. Дайте каждому свой bundle identifier и своё название приложения, чтобы все три могли стоять на одном телефоне, не перезаписывая друг друга. Для этого достаточно динамического app.config.ts, который читает переменную APP_VARIANT.

Одно правило стоит повторять всей команде: всё, что попадает в бандл приложения, публично. Переменные с префиксом EXPO_PUBLIC_ вкомпилируются в JavaScript, который уходит на каждый телефон. Секретам API место на вашем сервере, а приложение общается с сервером.

4. Настройте подписание один раз и как следует

Именно на подписании при первом запуске теряют дни.

  • iOS требует членства в Apple Developer Program, сертификата для дистрибуции и provisioning-профилей. EAS может создать их и управлять ими за вас — я это рекомендую, если нет причин поступить иначе.
  • На Android ключей два. При Play App Signing ключ, которым подписывается то, что устанавливают пользователи, хранит Google, а у вас остаётся ключ загрузки (upload key). Сделайте его резервную копию. Если потеряете — можно запросить сброс, но время вы потеряете.
  • Тщательно выбирайте bundle identifier и имя пакета. Они постоянны. Приложение можно переименовать, но сменить его идентификатор нельзя.

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

5. Как можно раньше ставьте сборки на реальные телефоны

Симуляторы скрывают проблемы, которые действительно важны: медленные устройства, реальные сети, уведомления, диплинки, запросы разрешений. Сборки должны оказаться на реальных телефонах в первые недели, а не в последние.

  • TestFlight доставляет сборку внутренним тестировщикам через несколько минут после её обработки.
  • Трек внутреннего тестирования Google Play делает то же самое на Android.

Отдельно заложите в план одно правило Google Play. Новый личный аккаунт разработчика должен провести закрытое тестирование минимум с 12 тестировщиками, которые остаются в тесте непрерывно не менее 14 дней, и только после этого может подать заявку на доступ к продакшену. Эти две недели в конце не сожмёшь, поэтому начинайте заранее или публикуйтесь с аккаунта организации, на который это правило не распространяется.

6. Заполните формы, которые блокируют запуск

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

  • Декларации о приватности. Раздел App Privacy у Apple и форма Data safety в Google Play должны соответствовать тому, что на самом деле собирают приложение и каждый SDK в нём: аналитика, отчёты о сбоях, реклама, аутентификация. Составьте список SDK, прежде чем браться за любую из форм.
  • Удаление аккаунта. Если в приложении можно создать аккаунт, Apple требует, чтобы удаление аккаунта можно было начать прямо из приложения. Google Play требует путь внутри приложения и веб-ссылку, по которой можно запросить удаление. Делайте это полноценной функцией, а не письмом в поддержку.
  • Privacy manifests на iOS. Apple требует их для определённых системных API, а многие SDK эти API используют. Обычно достаточно держать SDK в актуальном состоянии.
  • Вход через соцсети. Если вы предлагаете вход через сторонний сервис, Apple, как правило, требует добавить и равноценный вариант, ориентированный на приватность. На практике это обычно Sign in with Apple.
  • Платежи. Цифровые товары и подписки, которые используются внутри приложения, как правило, должны проходить через систему встроенных покупок каждого магазина. Правила различаются по регионам и в последнее время меняются, так что сверяйтесь с актуальными требованиями для тех рынков, на которых запускаетесь. Сервис подписок вроде RevenueCat избавляет от необходимости самому писать валидацию чеков для двух магазинов.

7. Подготовьтесь к ревью

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

Напишите для ревьюеров заметки, объясняющие всё неочевидное, приложите рабочий демо-аккаунт и заложите на первую отправку несколько дней запаса. Последующие ревью обычно проходят быстрее, но вопросы возникают именно на первой отправке.

8. Спланируйте первое обновление до запуска

Выкатить исправление придётся в первые же дни после запуска. Заранее знайте, как вы это сделаете.

  • Изменения в JavaScript и ассетах можно выпускать как обновления по воздуху (OTA), например через EAS Update, без нового ревью в магазине. Привязывайте каждое обновление к runtime version, чтобы JavaScript никогда не попал в нативный бинарник, под который он не собирался. Используйте такие обновления для исправлений и улучшений. Магазины ожидают, что приложение, которое устанавливают люди, остаётся тем самым приложением, которое прошло ревью.
  • Нативные изменения — новый нативный модуль, разрешение или обновление SDK — требуют новой сборки для магазина.
  • Раскатывайте постепенно. Phased release в App Store и staged rollouts в Google Play позволяют сначала выпустить версию на часть пользователей и остановиться, если растёт число сбоев.

Следите за требованиями платформ. Google Play каждый год поднимает минимальный target API level, а Expo выпускает новые SDK несколько раз в год. Небольшие регулярные обновления обходятся намного дешевле, чем одно большое раз в два года.

Короткий чеклист перед отправкой

  1. Bundle identifier и имя пакета утверждены, все три варианта приложения работают.
  2. Подписание настроено, резервная копия ключа загрузки сделана.
  3. Тестирование на реальных устройствах на обеих платформах, включая медленный Android-телефон.
  4. Закрытое тестирование запущено заранее, если оно требуется для вашего аккаунта Google Play.
  5. Декларации о приватности учитывают каждый SDK, удаление аккаунта встроено.
  6. Заметки для ревьюеров и демо-аккаунт готовы.
  7. Отчёты о сбоях работают, а способ выпуска обновлений проверен до первого дня.

Как мы работаем в Syncra

Мы проводим мобильные приложения от пустого репозитория до обоих магазинов и поддерживаем их после запуска: React Native и Expo, бэкенд за ними и вся описанная выше работа с магазинами. iBeep, наше собственное приложение, проходит тот же путь. Когда iBeep появится в магазинах, вы найдёте его на этом сайте.

Другие заметки