Завантаження Source Map для React Native: деобфускація крашів
Чому source maps критичні для React Native?
Без source maps краш у Firebase Crashlytics виглядає як безглуздий рядок:
Fatal Exception: com.facebook.react.common.JavascriptException [email protected]:1:92847 [email protected]:1:15234 Номер 1:92847 — позиція в мініфікованому бандлі. Ми на десятках проектів бачили, як команди втрачають години, намагаючись відловити баги за такими стектрейсами. Source map перетворює це на читабельний шлях: onButtonPress @ src/screens/PaymentScreen.tsx:147:23. Без неї середній проект витрачає 2-4 години на кожен краш — при 15-30 крашах на місяць це 30-120 годин налагодження. Наше завдання — налаштувати автоматичне завантаження source maps у сервіс моніторингу, щоб кожен краш містив actionable інформацію. Робимо це під ключ, з інтеграцією у ваш CI, за 4 години — 2 дні. За 5 років ми налаштували цю систему для більш ніж 50 React Native проектів.
Як завантажити source maps у Firebase Crashlytics?
Використовуйте Firebase CLI: firebase crashlytics:mappingfile:upload --app "$FIREBASE_APP_ID" /path/to/map. Для проектів з Hermes потрібно попередньо скомпонувати два рівні source maps. Sentry простіший: він сам компонує map при завантаженні, що робить налаштування в 2 рази швидше. Ось покрокова інструкція:
- Встановіть Firebase CLI та авторизуйтесь:
npm install -g firebase-tools && firebase login:ci. - Зберіть release-бандл з source maps.
- Якщо використовуєте Hermes, виконайте композицію source maps.
- Завантажте source map у Crashlytics:
firebase crashlytics:mappingfile:upload --app "$FIREBASE_APP_ID" android/app/build/generated/sourcemaps/react/release/index.android.bundle.map - Для Sentry використовуйте
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/ - Перевірте, що версія в SDK збігається з переданою в CLI.
Приклад інтеграції в GitHub Actions — source map завантаження
- name: Upload Source Maps to Crashlytics run: | 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 }} Генерація source maps
React Native в production bundle мініфікує та об'єднує весь JS-код в один файл (index.android.bundle / main.jsbundle). Паралельно генерується source map (index.android.bundle.map) — таблиця відповідностей між позиціями в бандлі та вихідним кодом. Crashlytics та Sentry приймають ці 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 maps?
Hermes компілює JS-бандл у байткод, додаючи додатковий шар. Без композиції сервіси моніторингу отримують маппінг лише на JS-бандл, а не на вихідний код. Наприклад, стек вказує на рядок у бандлі, а не в *.tsx файлі. Скрипт compose-source-maps.js об'єднує обидва маппінги. Для проектів з Hermes (увімкнено за замовчуванням з RN 0.70+) виконайте:
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 android/app/build/generated/sourcemaps/react/release/index.android.bundle.map Без цього кроку Firebase Crashlytics покаже стектрейс, що посилається на рядки JS-бандлу, а не на вихідний TypeScript-файл. Sentry, навпаки, автоматично компонує source maps при завантаженні, що робить його в 2 рази простішим у налаштуванні для Hermes.
Порівняння сервісів моніторингу
| Параметр | Firebase Crashlytics | Sentry |
|---|---|---|
| CLI | firebase-tools | @sentry/cli |
| Hermes compose | потрібен ручний compose | підтримує автоматично |
| Версіонування | через --app та маппінг |
обов'язковий release в SDK та CLI |
| Складність інтеграції | вища для Hermes | нижча — менше кроків |
Sentry простіший у налаштуванні, особливо для проектів з Hermes: він сам компонує source maps при завантаженні. Але Firebase залишається популярним через вбудовану в Firebase екосистему. Обирайте під свій стек.
Типові помилки при деобфускації
| Помилка | Причина | Рішення |
|---|---|---|
| Стек не декодується | Невідповідність версій | Використовуйте єдиний формат APP_VERSION+BUILD_NUMBER |
| Source map не знайдено | Не завантажено в CI | Додайте крок завантаження після збірки |
| Стек посилається на бандл | Hermes без композиції | Виконайте compose-source-maps.js |
Що входить у роботу
Ми беремо на себе повне налаштування:
- аналіз поточної конфігурації збірки (Hermes, наявність bundle, CI)
- написання скриптів композиції source maps для Hermes (якщо потрібно)
- інтеграція завантаження в CI (GitHub Actions, GitLab CI, Bitrise — будь-який)
- узгодження формату версії та впровадження в SDK
- перевірка деобфускації на тестовому краші
- документація процесу для вашої команди
Гарантуємо, що після налаштування ви будете отримувати читабельні стектрейси на кожен краш. Ми зробили це для більш ніж 50 React Native проектів за 5 років роботи. Зв'яжіться з нами для оцінки вашого проекту — консультація безкоштовна. Отримайте готове рішення з автоматичним завантаженням source maps, яке скоротить час налагодження на 70%.
Терміни та вартість
Термін: 4 години — 2 дні залежно від поточного налаштування CI та наявності Hermes. Вартість розраховується індивідуально. Напишіть нам — оцінимо ваш проект безкоштовно.







