React Native Performance Playbook: 9 Steps to Speed Up Your App Before Launch
Users bounce when apps stall; these steps focus on cold start, bundle weight, and scroll smoothness you can ship this week.
1) Profile cold start and UI on real devices
Use Flipper performance plugins and Hermes profiling to identify slow native modules and JS initialization. Measure Time to First Interaction and frame drops on mid-tier Android hardware.
2) Ship release builds to QA, not debug
Debug builds hide perf wins. Run `react-native run-android --variant release` and `xcodebuild -configuration Release` so QA benchmarks realistic binary size, startup time, and memory footprint.
3) Keep the bundle lean
Enable Hermes, remove unused polyfills and Moment locales, and configure Metro to exclude dev-only libraries. Split your code with dynamic imports for seldom-used flows and vendor chunks for analytics.
4) Lazy load screens and assets
Use React Navigation lazy options plus dynamic imports for heavy screens. Avoid global `require` calls for images; load them after the screen mounts and keep placeholders light.
5) Optimize images and icons
Serve right-sized assets, prefer WebP/AVIF where supported, and use vector icons instead of large PNG sprites. Cache frequently used images with FastImage or native caching.
6) Cache API responses and prefetch critical data
Use react-query or SWR to memoize responses and avoid duplicate calls. Prefetch session data and the home feed on the splash screen so the first screen renders without waiting on the network.
7) Minimize re-renders
Wrap expensive components with `React.memo`, pass stable callbacks with `useCallback`, and avoid prop drilling that triggers whole-tree updates. Use `FlashList` or an optimized `FlatList` with proper `keyExtractor` and `getItemLayout` for long lists.
8) Move heavy work off the JS thread
Offload JSON parsing, image resizing, and crypto to native modules or background threads. Use `InteractionManager.runAfterInteractions` to postpone non-critical work until after the first paint.
9) Monitor on devices and in production
Add Firebase Performance or Sentry Performance to capture startup, HTTP timing, and UI hangs. Set budgets for cold start (under 2 seconds on mid-tier Android) and scroll FPS, and alert on regressions.
Launch checklist
- Release build measured on low-mid devices
- Core flows lazy loaded with cached API data
- Images compressed and cached, no oversized sprites
- Perf monitoring enabled with budgets recorded for the team
Users bounce when apps stall; these steps focus on cold start, bundle weight, and scroll smoothness you can ship this week.
1) Profile cold start and UI on real devices
Use Flipper performance plugins and Hermes profiling to identify slow native modules and JS initialization. Measure Time to First Interaction and frame drops on mid-tier Android hardware.
2) Ship release builds to QA, not debug
Debug builds hide perf wins. Run `react-native run-android --variant release` and `xcodebuild -configuration Release` so QA benchmarks realistic binary size, startup time, and memory footprint.
3) Keep the bundle lean
Enable Hermes, remove unused polyfills and Moment locales, and configure Metro to exclude dev-only libraries. Split your code with dynamic imports for seldom-used flows and vendor chunks for analytics.
4) Lazy load screens and assets
Use React Navigation lazy options plus dynamic imports for heavy screens. Avoid global `require` calls for images; load them after the screen mounts and keep placeholders light.
5) Optimize images and icons
Serve right-sized assets, prefer WebP/AVIF where supported, and use vector icons instead of large PNG sprites. Cache frequently used images with FastImage or native caching.
6) Cache API responses and prefetch critical data
Use react-query or SWR to memoize responses and avoid duplicate calls. Prefetch session data and the home feed on the splash screen so the first screen renders without waiting on the network.
7) Minimize re-renders
Wrap expensive components with `React.memo`, pass stable callbacks with `useCallback`, and avoid prop drilling that triggers whole-tree updates. Use `FlashList` or an optimized `FlatList` with proper `keyExtractor` and `getItemLayout` for long lists.
8) Move heavy work off the JS thread
Offload JSON parsing, image resizing, and crypto to native modules or background threads. Use `InteractionManager.runAfterInteractions` to postpone non-critical work until after the first paint.
9) Monitor on devices and in production
Add Firebase Performance or Sentry Performance to capture startup, HTTP timing, and UI hangs. Set budgets for cold start (under 2 seconds on mid-tier Android) and scroll FPS, and alert on regressions.
Launch checklist
- Release build measured on low-mid devices
- Core flows lazy loaded with cached API data
- Images compressed and cached, no oversized sprites
- Perf monitoring enabled with budgets recorded for the team