How to reduce a Production React Native 0.81 APK Size
Step 1: Stop Building for the Museum (Target only arm64)
Most generic tutorials tell you to “split APKs” by architecture. We went a step further. We realized that if your minSdkVersion is 29 or higher (Android 10+), you are exclusively serving 64-bit devices.
Why support 32-bit chips from 2014? You shouldn’t.
- The Reality: 95%+ of active devices run arm64-v8a.
- The Play Store Mandate: Google requires 64-bit support anyway.
How we implemented it:
In android/app/build.gradle, we told Gradle to stop building a “fat” APK and focus solely on modern hardware.
gradle
def enableSeparateBuildPerCPUArchitecture = true
splits {
abi {
reset()
enable enableSeparateBuildPerCPUArchitecture
universalApk false // Don't build the heavy universal version
include "arm64-v8a" // Only modern 64-bit devices
}
}The result: By dropping armeabi-v7a and x86, we instantly reclaimed ~30% of our space.
Step 2: Declutter Your Resources (Ditch the Dependencies’ Languages)
Here is a sneaky one. Your app might only support English, Arabic, and French. But your dependencies (Google Play Services, Firebase, etc.) bundle translations for 50+ languages.
That is megabytes of wasted space.
The fix: In defaultConfig, explicitly tell Android to discard everything else.
gradle
defaultConfig {
// ...
resConfigs "ar", "en", "fr" // Keep only the languages you actually use
}The result: Several MB removed instantly. No code changes required.
Step 3: Turn on the “Aggressive” Optimizers
We enabled four flags in our release build type. If you aren’t using shrinkResources and crunchPngs, you are leaving free space on the table.
gradle
buildTypes {
release {
minifyEnabled true // Removes dead code
shrinkResources true // Removes unused drawables/assets
crunchPngs true // Lossless PNG compression
zipAlignEnabled true // Runtime memory optimization
proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
}
}Note: shrinkResources works best when minifyEnabled is also true — they are a team.
Step 4: The “No-Compromise” ProGuard Config (Battle-Tested)
This is where most developers get scared. A bad ProGuard rule breaks your app. A good one removes 10% of your size.
Get Neha Bisht’s stories in your inbox
Join Medium for free to get updates from this writer.
We spent hours testing a configuration that keeps crash reporting (SourceFile,LineNumberTable) and React Native 0.81’s internals intact, while stripping out verbose logs.
Our proguard-rules.pro (Abridged but essential):
proguard
# Aggressive optimization passes
-optimizationpasses 3
-allowaccessmodification
-repackageclasses ''
# Remove logs (Keep errors for debugging)
-assumenosideeffects class android.util.Log {
public static *** d(...);
public static *** v(...);
public static *** i(...);
}
# Preserve stack traces for Crashlytics
-keepattributes SourceFile,LineNumberTable,Signature
# React Native 0.81 Core Keep rules
-keep class com.facebook.hermes.** { *; }
-keep class com.facebook.react.** { *; }
-keep class com.facebook.jni.** { *; }
# Keep Native Methods
-keepclassmembers class * {
@com.facebook.react.bridge.ReactMethod *;
}
# Third-party libraries (Reanimated, SVG, FastImage, Firebase)
-keep class com.swmansion.reanimated.** { *; }
-keep class com.dylanvann.fastimage.** { *; }
-keep class com.google.firebase.** { *; }
-dontwarn okhttp3.**Step 5: Confirm Hermes is Actually On
Hermes is React Native’s secret weapon. It compiles JavaScript to bytecode, resulting in smaller bundles and faster startups. In RN 0.81, it is the default, but verify android/gradle.properties:
properties
hermesEnabled=trueIf this is false, you are shipping a human-readable JS bundle (which is huge). If it is true, you are shipping optimized bytecode.
How to Validate Your Build
# 1. Clean the cache
cd android && ./gradlew clean
# 2. Build the release APK
./gradlew assembleRelease
# 3. Check the output size
ls -lh app/build/outputs/apk/release/*.apk
# 4. Bonus: Inspect what's inside (Android Studio > Build > Analyze APK)The Final Checklist
Before you ship, ensure you have checked every box:
- Architecture: Only arm64-v8a (or split appropriately).
- Universal APK: Set to false.
- Languages: Only your specific resConfigs.
- Resource Shrinking: shrinkResources true.
- ProGuard: Applied the “optimize” file and our custom rules.
- Hermes: Confirmed true in gradle.properties.
- Real Device Test: Verified the app launches and crashes report properly.
The Takeaway
Reducing your APK size isn’t about choosing between performance and stability. By being precise about your target architecture, aggressive about resource stripping, and disciplined with ProGuard, you can have both.








