Android

React Native ProGuard ve R8

AndroidR8ProGuard

Android release’de R8 minify/shrink’in RN, Hermes ve New Architecture kodunu neden kırdığı; keep kuralları ve mapping.txt stratejisi.

EG

Emre Gürbüz

21 Temmuz 2026 · 4 dk okuma

Android release build’lerinde R8 (ProGuard’ın halefi — kod küçültme ve karartma aracı) sınıfları siler, inline eder, obfuscate eder. React Native uygulamalarında bu pipeline, debug’da mükemmel çalışan bir ekranın production’da NativeModule not found üretmesinin en sık köprüsüdür.

R8 “güvenlik için aç/kapa” değildir; entry point grafiği, reflection sözleşmesi ve mapping artifact yönetimi problemidir.

R8 neden var, RN’de neden acıtır?

R8 üç işi birleştirir:

  1. Shrinking: Ulaşılamayan sınıfları/metotları siler
  2. Optimization: Inline, dead code elimination
  3. Obfuscation: İsimleri kısaltır (a.b.c)

RN ekosistemi bu modele ters düşer: çekirdek RN, Hermes, Reanimated ve birçok SDK reflection (runtime’da string ile sınıf bulma), JNI veya string sınıf adı bekler. R8 “kullanılmıyor” der; runtime’da modül yüklenmez. Crash genelde ilk açılışta değil, belirli ekranda (ödeme, kamera, push) çıkar.

Shrinking vs obfuscation

Çoğu ekip obfuscation’ı suçlar; asıl kırılma çoğu zaman shrinking’dendir. Teşhis: önce minify kapalı release alın; crash kaybolduysa suçlu R8’tir. Sonra doğru keep kuralı yazın.

Gradle yapılandırması

Release’de minify açmak standarttır:

android {
  buildTypes {
    release {
      minifyEnabled true
      shrinkResources true
      proguardFiles \
        getDefaultProguardFile('proguard-android-optimize.txt'),
        'proguard-rules.pro'
    }
  }
}

proguard-android-optimize.txt agresiftir; JNI-heavy lib’lerde proguard-android.txt ile karşılaştırmalı smoke test yapın. shrinkResources dinamik resource adı kullanan SDK’lar için tools:keep ister.

Consumer ProGuard rules

Modern lib’ler kendi kurallarını yayınlar. Yine de “transitive rule yeter” varsayımı sık kırılır: eski Native Module, local monorepo modülü, codegen Turbo sınıfları. Her major dependency upgrade sonrası release smoke pipeline’a bağlı olsun.

Tipik keep stratejisi

“Her şeyi tut” olmamalı — APK şişer. Minimal ve kaynaklı kurallar:

# React Native çekirdek
-keep class com.facebook.react.** { *; }
-keep class com.facebook.hermes.** { *; }
-keep class com.facebook.jni.** { *; }

# Turbo Modules / Fabric JNI yüzeyleri
-keep class com.facebook.react.turbomodule.** { *; }
-keep class com.facebook.react.fabric.** { *; }

# Örnek: Reanimated + Gesture Handler
-keep class com.swmansion.reanimated.** { *; }
-keep class com.swmansion.gesturehandler.** { *; }

# JSON / Gson modelleri (reflection)
-keepclassmembers class * {
  @com.google.gson.annotations.SerializedName <fields>;
}

# WebView / JS bridge SDK'ları
-keep class com.example.paymentsdk.** { *; }

Ödeme, harita, reklam SDK’ları için resmi dokümantasyondaki snippet’i kopyalayın. Stack Overflow’dan -keep class ** { *; } hem güvenlik hem boyut kaybettirir.

R8 build log’undaki missing_rules.txt uyarılarını “noise” diye yutmayın — CI artifact olarak saklayın.

mapping.txt: birinci sınıf artifact

Obfuscation açıkken stack trace okunamaz. mapping.txt tek geri dönüş yoludur:

./gradlew :app:assembleRelease
# android/app/build/outputs/mapping/release/mapping.txt

Checklist:

  • Her release’de mapping CI artifact
  • Crashlytics / Sentry / Play Console’a upload
  • Binary version + build number ile eşleşik
  • Mapping silinmez — eski crash’ler körleşir

New Architecture ve R8

Fabric, Turbo Modules ve bridgeless daha fazla generated kod üretir. Codegen sınıfları shrink’e takılabilir.

Sık senaryolar:

  • Turbo codegen sınıfları silinir → registry’de yok
  • Fabric Component Descriptor shrink → custom view render olmaz
  • Interop sınıfları agresif optimize ile kırılır

Kritik: OTA yalnızca JS günceller. R8 sorunları native binary’ye aittir.

Debug stratejisi

  1. Minify kapalı release — crash kaybolduysa R8 suçlu
  2. Minify açık, obfuscation kapalı (geçici teşhis)
  3. R8 log ile hangi sınıfın silindiğini bulun
  4. Resmi kütüphane kuralını ekleyin
  5. Minify açık release + E2E smoke
  6. Mapping upload + staged rollout

Sık tuzaklar

  • Sadece debug test
  • Flipper release’de
  • shrinkResources + Lottie / dinamik tema
  • Vendor SDK güncelleme without ProGuard review
  • JS source map ile native mapping karıştırmak

Production checklist

  • minifyEnabled yalnızca release’te
  • proguard-rules.pro + consumer rules gözden geçirildi
  • Mapping arşivlendi ve crash servisine upload
  • Minify açık/kapalı A/B smoke: login, pay, kamera, deep link
  • Hermes / RN / Reanimated / New Arch keep’leri güncel
  • missing_rules.txt CI’da inceleniyor
  • Staged rollout + crash-free cohort aktif

Özet

R8, RN production’ının görünmez güvenlik ağıdır — yanlış yapılandırıldığında mayın tarlası. Minify’ı açık tutun, keep’leri minimal yazın, mapping’i birinci sınıf artifact yapın, New Arch geçişinde native yüzey artışını plana dahil edin. Aksi halde “yalnızca Play Store kullanıcılarında” hayalet crash birikir ve OTA ile çözülemez.


Diğer yazılar