A release build does not ship JavaScript source. Gradle 19,597 runs hermesc over the bundle (Hermes) and puts the bytecode in the APK, where the release APK built for End-to-End Testing with Detox holds it:
unzip -o -q app-release.apk assets/index.android.bundle
ls -l assets/index.android.bundle; file assets/index.android.bundle-rw-r--r-- 1 dev dev 4915416 Jan 1 1981 assets/index.android.bundle assets/index.android.bundle: Hermes JavaScript bytecode, version 98
Bytecode makes startup faster, not the app smaller. npx expo export --platform android produces the same production bundle outside Gradle, and --no-bytecode keeps it as minified JavaScript, so the two can be compared directly:
| Bundle (2,141 modules) | Size | gzip -9 |
|---|---|---|
| entry-….hbc, Hermes bytecode | 5,950,323 bytes | 2,518,099 bytes |
| entry-….js, minified JavaScript | 4,300,707 bytes | 1,021,154 bytes |
The bytecode is 38% larger and compresses to two and a half times the size, because it stores precompiled instructions, a string table and function metadata rather than terse source. What it saves is work on the phone: Hermes maps the file into memory and starts executing without parsing or compiling anything. To make the bundle smaller, remove code instead. EXPO_ATLAS=true npx expo export records every module with its size in .expo/atlas.jsonl, and npx expo-atlas .expo/atlas.jsonl shows them as a graph, so you can see which dependency pulled in which megabyte. Replace heavy libraries with lighter ones or platform APIs, import only what you use from large packages, and keep demo and debug code out of release bundles.