Настройка Source Map загрузки для деобфускации крашей React Native

TRUETECH занимается разработкой, поддержкой и обслуживанием мобильных приложений iOS, Android, PWA. Имеем большой опыт и экспертизу для публикации мобильных приложений в популярные маркеты Google Play, App Store, Amazon, AppGallery и другие.
Разработка и поддержка любых видов мобильных приложений:
Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Предлагаемые услуги
Показано 1 из 1 услугВсе 1735 услуг
Настройка Source Map загрузки для деобфускации крашей React Native
Средняя
от 4 часов до 2 рабочих дней
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1054
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    864
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    445

Настройка Source Map загрузки для деобфускации крашей React Native

В Firebase Crashlytics крэш выглядит примерно так:

Fatal Exception: com.facebook.react.common.JavascriptException
[email protected]:1:92847
[email protected]:1:15234

Строка 1:92847 в минифицированном бандле. Без source maps невозможно понять, в каком файле и функции произошёл крэш. Source map mapping превращает этот стектрейс в читаемый: onButtonPress @ src/screens/PaymentScreen.tsx:147:23.

Как работает деобфускация

React Native в production bundle минифицирует и объединяет весь JS-код в один файл (index.android.bundle / main.jsbundle). Параллельно генерируется source map (index.android.bundle.map) — таблица соответствий между позициями в бандле и исходным кодом.

Crashlytics и Sentry принимают эти source maps и хранят на своих серверах. Когда приходит крэш — автоматически применяют маппинг и показывают исходный стектрейс.

Генерация source maps

# Android
react-native bundle \
  --platform android \
  --dev false \
  --entry-file index.js \
  --bundle-output android/app/src/main/assets/index.android.bundle \
  --sourcemap-output android/app/src/main/assets/index.android.bundle.map

# iOS
react-native bundle \
  --platform ios \
  --dev false \
  --entry-file index.js \
  --bundle-output ios/main.jsbundle \
  --sourcemap-output ios/main.jsbundle.map

В стандартном ./gradlew bundleRelease source map генерируется автоматически в app/build/generated/sourcemaps/react/release/. Но у него есть проблема: при hermes-компиляции нужен составной source map — hermes создаёт второй уровень маппинга (bytecode → JS bundle), который нужно скомпоновать с первым (JS bundle → TypeScript).

Hermes и составной source map

Для проектов с Hermes (включён по умолчанию с RN 0.70+):

# Compose source maps: hermes-engine + JS bundle
node_modules/react-native/scripts/compose-source-maps.js \
  android/app/build/generated/sourcemaps/react/release/index.android.bundle.packager.map \
  android/app/build/generated/sourcemaps/react/release/index.android.bundle.compiler.map \
  -o android/app/build/generated/sourcemaps/react/release/index.android.bundle.map

Без этого шага Firebase Crashlytics покажет стектрейс, ссылающийся на строки JS-бандла, а не на исходный TypeScript-файл.

Загрузка в Firebase Crashlytics

# Установка Firebase CLI
npm install -g firebase-tools

# Загрузка source map
firebase crashlytics:mappingfile:upload \
  --app "$FIREBASE_APP_ID" \
  android/app/build/generated/sourcemaps/react/release/index.android.bundle.map

В CI это шаг после сборки:

- name: Upload Source Maps to Crashlytics
  run: |
    # Compose Hermes source maps
    node node_modules/react-native/scripts/compose-source-maps.js \
      android/app/build/generated/sourcemaps/react/release/index.android.bundle.packager.map \
      android/app/build/generated/sourcemaps/react/release/index.android.bundle.compiler.map \
      -o /tmp/composed.map

    firebase crashlytics:mappingfile:upload \
      --app "$FIREBASE_APP_ID_ANDROID" \
      /tmp/composed.map
  env:
    FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}

Загрузка в Sentry

Sentry использует CLI sentry-cli:

npm install -g @sentry/cli

sentry-cli releases new "$RELEASE_VERSION"

sentry-cli sourcemaps upload \
  --org "$SENTRY_ORG" \
  --project "$SENTRY_PROJECT" \
  --release "$RELEASE_VERSION" \
  android/app/build/generated/sourcemaps/react/release/

В Sentry нужно передавать release в SDK:

Sentry.init({
  dsn: Config.SENTRY_DSN,
  release: `${DeviceInfo.getBundleId()}@${DeviceInfo.getVersion()}+${DeviceInfo.getBuildNumber()}`,
});

Версия должна совпадать с тем, что передаётся при загрузке source maps.

Проблема с версионированием

Частая ошибка: source maps загружаются для одной версии (1.2.3), а в SDK передаётся другая (1.2.3+42). Крэши не деобфусцируются. Нужно зафиксировать единый формат версии и использовать его в обоих местах — CI переменная VERSION=$APP_VERSION+$BUILD_NUMBER.

Процесс

Проверка включения Hermes → настройка генерации source maps в build pipeline → скрипт compose для Hermes → добавление шага загрузки в CI → проверка деобфускации на тестовом крэше → документация формата версий.

Срок: 4 часа — 2 дня в зависимости от текущей настройки CI и наличия Hermes. Стоимость рассчитывается индивидуально.