Have you ever uploaded a Rork-generated app to TestFlight and been met with an App Store Connect warning that the binary is too large? I hit that exact wall while rebuilding one of my own wallpaper and wellness apps in Rork. The very first archive came in close to 180MB, and I had to get serious about slimming it down before shipping.
Here's the thing I wish I'd known sooner: most Rork-generated apps can be shrunk by 50–60% without rewriting a single line of feature code. What follows is the exact path I took, along with the numbers I measured at each step with xcrun and the Xcode Organizer.
Start by Pinpointing Where the Fat Lives
Without measuring, you'll "feel lighter" after each change and quit before the real wins. A typical Rork-generated app's binary can be broken into five chunks:
- The JavaScript bundle (
main.jsbundleor Hermes bytecode) - Images, fonts, and videos shipped as assets
- Native library binaries from Expo modules
- Localized resources (translation files and per-locale assets)
- Debug symbols (
dSYMand unstripped native code)
On iOS, open Xcode → Organizer → Archives → Download App Size Report to see the post-App-Thinning download size split by cause. On Android, inspect output-metadata.json from ./gradlew :app:bundleRelease, or run APK Analyzer for a per-module breakdown. The goal is to replace "it feels big" with a sentence like "images take up 72MB", because only then can you build a reduction plan.
Re-Encode Assets with the Right Format
In roughly 7 out of 10 bloated Rork apps I've worked on, the largest culprit is image assets. Rork generates high-quality placeholder imagery that fits your prompt, which is convenient — but bundled as PNG, and especially for wallpaper or wellness apps, you'll blow past 100MB in a heartbeat.
Here's the three-step routine I run on every new project:
# 1. Batch-convert to WebP (keep SVG and transparency-critical PNGs untouched)
# brew install webp to get cwebp
find assets/images -type f \( -name "*.png" -o -name "*.jpg" \) -print0 \
| xargs -0 -I {} cwebp -q 82 "{}" -o "{}.webp"
# 2. Compare original vs WebP sizes
du -sh assets/images/**/*.png assets/images/**/*.webp | sort -h | tail -20
# 3. Delete originals and update references in one sweep
find assets/images -type f \( -name "*.png" -o -name "*.jpg" \) -delete
rg -l "\.png\"" src/ | xargs sed -i '' 's/\.png"/\.webp"/g'On the app I was slimming down, image assets dropped from 84MB to 21MB — a 75% cut. React Native supports WebP natively, but flattening transparent PNGs can occasionally break rendering on Android, so keep icon assets that rely on transparency in their original format as a safety net.
If you want to go further on image delivery, I've written a companion piece on image optimization and caching strategies for Rork apps that covers remote CDN patterns and expo-image configuration.
Make the JavaScript Bundle Explain Itself
If images are handled and the binary is still heavy, the next suspect is a fat dependency that shouldn't be there. Since Expo SDK 55, running npx expo export --dump-sourcemap gives you a sourcemap you can feed into react-native-bundle-visualizer for a per-module treemap.
# Install and analyze
npm install -D react-native-bundle-visualizer
npx react-native-bundle-visualizer --platform ios --dev falseThis usually surfaces the usual suspects: lodash imported wholesale (70KB+), or moment with its timezone data weighing in above 400KB. Swapping lodash for lodash-es with named imports, and moment for date-fns or dayjs, can shave 500KB combined without touching product code.
One Rork-specific gotcha: freshly generated projects sometimes ship with @babel/preset-env in babel.config.js even though Expo's babel-preset-expo already handles everything. Removing the redundant preset alone trims tens of kilobytes from the release bundle.
Tighten the Native Layer with Hermes and ProGuard
On iOS, confirm Hermes is enabled (it's the default in Expo SDK 55 and above). On Android, make sure both enableProguardInReleaseBuilds = true and enableShrinkResourcesInReleaseBuilds = true are set in android/app/build.gradle.
// android/app/build.gradle
android {
buildTypes {
release {
shrinkResources true
minifyEnabled true
proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
}
}
}For Android, turning on ABI splits lets you ship an arm64-v8a-only APK, cutting the user-downloaded size roughly in half. If you're using Google Play, simply uploading an App Bundle (AAB) lets Play handle device-specific slicing for you. ABI splits matter most when you're distributing APKs directly, such as through an enterprise channel.
Use App Thinning and On-Demand Resources to Lower Real Download Size
If "total app size" in App Store Connect is still painful after the steps above, the next lever is App Thinning on iOS. Rork tends to emit flat asset files, but if your app — say, a wallpaper app — wants to deliver different resolutions for different devices, register those images in Assets.xcassets with 1x / 2x / 3x slots. The end user will then only download the set matching their device.
On-Demand Resources go one step further: they let you ship a minimal first-boot binary and fetch the rest of your resources later, such as during a tutorial. The payoff is huge for learning and gaming apps, but the integration cost is meaningful. For most Rork apps I'd start with plain App Thinning and reserve ODR for when it clearly pays off.
For the performance angle adjacent to size, see practical techniques for cutting Rork app startup time and the broader Rork app performance optimization guide. Size and startup are a pair — tackle them together and the user-visible improvement compounds.
Your Next Step
Trying to halve binary size in a single pass usually stalls out. The faster path is to do 20–40% cuts in sequence: measure first, then images, then the JavaScript bundle, then the native layer. Open the Xcode Organizer's App Size Report today and find your single heaviest component — that's tomorrow's target.
For image-heavy apps, a WebP pass alone can vaporize hundreds of megabytes. It's one of the highest-leverage changes you can make. Beyond silencing App Store size warnings, a smaller binary means users on slow networks don't abandon the install halfway through. Treat the optimization as a welcome gift to your first-time users — that's the mindset shift I try to keep when I'm tempted to ship "just one more megabyte".