|
| 1 | +--- |
| 2 | +name: react-native-best-practices |
| 3 | +description: Provides React Native performance optimization guidelines for FPS, TTI, bundle size, memory leaks, re-renders, and animations. Applies to tasks involving Hermes optimization, JS thread blocking, bridge overhead, FlashList, native modules, or debugging jank and frame drops. |
| 4 | +license: MIT |
| 5 | +metadata: |
| 6 | + author: Callstack |
| 7 | + tags: react-native, expo, performance, optimization, profiling |
| 8 | +--- |
| 9 | + |
| 10 | +# React Native Best Practices |
| 11 | + |
| 12 | +## Overview |
| 13 | + |
| 14 | +Performance optimization guide for React Native applications, covering JavaScript/React, Native (iOS/Android), and bundling optimizations. Based on Callstack's "Ultimate Guide to React Native Optimization". |
| 15 | + |
| 16 | +## Skill Format |
| 17 | + |
| 18 | +Each reference file follows a hybrid format for fast lookup and deep understanding: |
| 19 | + |
| 20 | +- **Quick Pattern**: Incorrect/Correct code snippets for immediate pattern matching |
| 21 | +- **Quick Command**: Shell commands for process/measurement skills |
| 22 | +- **Quick Config**: Configuration snippets for setup-focused skills |
| 23 | +- **Quick Reference**: Summary tables for conceptual skills |
| 24 | +- **Deep Dive**: Full context with When to Use, Prerequisites, Step-by-Step, Common Pitfalls |
| 25 | + |
| 26 | +**Impact ratings**: CRITICAL (fix immediately), HIGH (significant improvement), MEDIUM (worthwhile optimization) |
| 27 | + |
| 28 | +## When to Apply |
| 29 | + |
| 30 | +Reference these guidelines when: |
| 31 | + |
| 32 | +- Debugging slow/janky UI or animations |
| 33 | +- Investigating memory leaks (JS or native) |
| 34 | +- Optimizing app startup time (TTI) |
| 35 | +- Reducing bundle or app size |
| 36 | +- Writing native modules (Turbo Modules) |
| 37 | +- Profiling React Native performance |
| 38 | +- Reviewing React Native code for performance |
| 39 | + |
| 40 | +## Priority-Ordered Guidelines |
| 41 | + |
| 42 | +| Priority | Category | Impact | Prefix | |
| 43 | +| -------- | ------------------ | ----------- | ---------------------- | |
| 44 | +| 1 | FPS & Re-renders | CRITICAL | `js-*` | |
| 45 | +| 2 | Bundle Size | CRITICAL | `bundle-*` | |
| 46 | +| 3 | TTI Optimization | HIGH | `native-*`, `bundle-*` | |
| 47 | +| 4 | Native Performance | HIGH | `native-*` | |
| 48 | +| 5 | Memory Management | MEDIUM-HIGH | `js-*`, `native-*` | |
| 49 | +| 6 | Animations | MEDIUM | `js-*` | |
| 50 | + |
| 51 | +## Quick Reference |
| 52 | + |
| 53 | +### Critical: FPS & Re-renders |
| 54 | + |
| 55 | +**Profile first:** |
| 56 | + |
| 57 | +```bash |
| 58 | +# Open React Native DevTools |
| 59 | +# Press 'j' in Metro, or shake device → "Open DevTools" |
| 60 | +``` |
| 61 | + |
| 62 | +**Common fixes:** |
| 63 | + |
| 64 | +- Replace ScrollView with FlatList/FlashList for lists |
| 65 | +- Use React Compiler for automatic memoization |
| 66 | +- Use atomic state (Jotai/Zustand) to reduce re-renders |
| 67 | +- Use `useDeferredValue` for expensive computations |
| 68 | + |
| 69 | +### Critical: Bundle Size |
| 70 | + |
| 71 | +**Analyze bundle:** |
| 72 | + |
| 73 | +```bash |
| 74 | +npx react-native bundle \ |
| 75 | + --entry-file index.js \ |
| 76 | + --bundle-output output.js \ |
| 77 | + --platform ios \ |
| 78 | + --sourcemap-output output.js.map \ |
| 79 | + --dev false --minify true |
| 80 | + |
| 81 | +npx source-map-explorer output.js --no-border-checks |
| 82 | +``` |
| 83 | + |
| 84 | +**Common fixes:** |
| 85 | + |
| 86 | +- Avoid barrel imports (import directly from source) |
| 87 | +- Remove unnecessary Intl polyfills (Hermes has native support) |
| 88 | +- Enable tree shaking (Expo SDK 52+ or Re.Pack) |
| 89 | +- Enable R8 for Android native code shrinking |
| 90 | + |
| 91 | +### High: TTI Optimization |
| 92 | + |
| 93 | +**Measure TTI:** |
| 94 | + |
| 95 | +- Use `react-native-performance` for markers |
| 96 | +- Only measure cold starts (exclude warm/hot/prewarm) |
| 97 | + |
| 98 | +**Common fixes:** |
| 99 | + |
| 100 | +- Disable JS bundle compression on Android (enables Hermes mmap) |
| 101 | +- Use native navigation (react-native-screens) |
| 102 | +- Preload commonly-used expensive screens before navigating to them |
| 103 | + |
| 104 | +### High: Native Performance |
| 105 | + |
| 106 | +**Profile native:** |
| 107 | + |
| 108 | +- iOS: Xcode Instruments → Time Profiler |
| 109 | +- Android: Android Studio → CPU Profiler |
| 110 | + |
| 111 | +**Common fixes:** |
| 112 | + |
| 113 | +- Use background threads for heavy native work |
| 114 | +- Prefer async over sync Turbo Module methods |
| 115 | +- Use C++ for cross-platform performance-critical code |
| 116 | + |
| 117 | +## References |
| 118 | + |
| 119 | +Full documentation with code examples in [references/][references]: |
| 120 | + |
| 121 | +### JavaScript/React (`js-*`) |
| 122 | + |
| 123 | +| File | Impact | Description | |
| 124 | +| ------------------------------------------------------------- | -------- | ----------------------------------------- | |
| 125 | +| [js-lists-flatlist-flashlist.md][js-lists-flatlist-flashlist] | CRITICAL | Replace ScrollView with virtualized lists | |
| 126 | +| [js-profile-react.md][js-profile-react] | MEDIUM | React DevTools profiling | |
| 127 | +| [js-measure-fps.md][js-measure-fps] | HIGH | FPS monitoring and measurement | |
| 128 | +| [js-memory-leaks.md][js-memory-leaks] | MEDIUM | JS memory leak hunting | |
| 129 | +| [js-atomic-state.md][js-atomic-state] | HIGH | Jotai/Zustand patterns | |
| 130 | +| [js-concurrent-react.md][js-concurrent-react] | HIGH | useDeferredValue, useTransition | |
| 131 | +| [js-react-compiler.md][js-react-compiler] | HIGH | Automatic memoization | |
| 132 | +| [js-animations-reanimated.md][js-animations-reanimated] | MEDIUM | Reanimated worklets | |
| 133 | +| [js-uncontrolled-components.md][js-uncontrolled-components] | HIGH | TextInput optimization | |
| 134 | + |
| 135 | +### Native (`native-*`) |
| 136 | + |
| 137 | +| File | Impact | Description | |
| 138 | +| ----------------------------------------------------------------- | -------- | --------------------------------------------- | |
| 139 | +| [native-turbo-modules.md][native-turbo-modules] | HIGH | Building fast native modules | |
| 140 | +| [native-sdks-over-polyfills.md][native-sdks-over-polyfills] | HIGH | Native vs JS libraries | |
| 141 | +| [native-measure-tti.md][native-measure-tti] | HIGH | TTI measurement setup | |
| 142 | +| [native-threading-model.md][native-threading-model] | HIGH | Turbo Module threads | |
| 143 | +| [native-profiling.md][native-profiling] | MEDIUM | Xcode/Android Studio profiling | |
| 144 | +| [native-platform-setup.md][native-platform-setup] | MEDIUM | iOS/Android tooling guide | |
| 145 | +| [native-view-flattening.md][native-view-flattening] | MEDIUM | View hierarchy debugging | |
| 146 | +| [native-memory-patterns.md][native-memory-patterns] | MEDIUM | C++/Swift/Kotlin memory | |
| 147 | +| [native-memory-leaks.md][native-memory-leaks] | MEDIUM | Native memory leak hunting | |
| 148 | +| [native-android-16kb-alignment.md][native-android-16kb-alignment] | CRITICAL | Third-party library alignment for Google Play | |
| 149 | + |
| 150 | +### Bundling (`bundle-*`) |
| 151 | + |
| 152 | +| File | Impact | Description | |
| 153 | +| ------------------------------------------------- | -------- | -------------------------- | |
| 154 | +| [bundle-barrel-exports.md][bundle-barrel-exports] | CRITICAL | Avoid barrel imports | |
| 155 | +| [bundle-analyze-js.md][bundle-analyze-js] | CRITICAL | JS bundle visualization | |
| 156 | +| [bundle-tree-shaking.md][bundle-tree-shaking] | HIGH | Dead code elimination | |
| 157 | +| [bundle-analyze-app.md][bundle-analyze-app] | HIGH | App size analysis | |
| 158 | +| [bundle-r8-android.md][bundle-r8-android] | HIGH | Android code shrinking | |
| 159 | +| [bundle-hermes-mmap.md][bundle-hermes-mmap] | HIGH | Disable bundle compression | |
| 160 | +| [bundle-native-assets.md][bundle-native-assets] | HIGH | Asset catalog setup | |
| 161 | +| [bundle-library-size.md][bundle-library-size] | MEDIUM | Evaluate dependencies | |
| 162 | +| [bundle-code-splitting.md][bundle-code-splitting] | MEDIUM | Re.Pack code splitting | |
| 163 | + |
| 164 | +## Searching References |
| 165 | + |
| 166 | +```bash |
| 167 | +# Find patterns by keyword |
| 168 | +grep -l "reanimated" references/ |
| 169 | +grep -l "flatlist" references/ |
| 170 | +grep -l "memory" references/ |
| 171 | +grep -l "profil" references/ |
| 172 | +grep -l "tti" references/ |
| 173 | +grep -l "bundle" references/ |
| 174 | +``` |
| 175 | + |
| 176 | +## Problem → Skill Mapping |
| 177 | + |
| 178 | +| Problem | Start With | |
| 179 | +| ------------------------------ | ----------------------------------------------------------------------------------------------------- | |
| 180 | +| App feels slow/janky | [js-measure-fps.md][js-measure-fps] → [js-profile-react.md][js-profile-react] | |
| 181 | +| Too many re-renders | [js-profile-react.md][js-profile-react] → [js-react-compiler.md][js-react-compiler] | |
| 182 | +| Slow startup (TTI) | [native-measure-tti.md][native-measure-tti] → [bundle-analyze-js.md][bundle-analyze-js] | |
| 183 | +| Large app size | [bundle-analyze-app.md][bundle-analyze-app] → [bundle-r8-android.md][bundle-r8-android] | |
| 184 | +| Memory growing | [js-memory-leaks.md][js-memory-leaks] or [native-memory-leaks.md][native-memory-leaks] | |
| 185 | +| Animation drops frames | [js-animations-reanimated.md][js-animations-reanimated] | |
| 186 | +| List scroll jank | [js-lists-flatlist-flashlist.md][js-lists-flatlist-flashlist] | |
| 187 | +| TextInput lag | [js-uncontrolled-components.md][js-uncontrolled-components] | |
| 188 | +| Native module slow | [native-turbo-modules.md][native-turbo-modules] → [native-threading-model.md][native-threading-model] | |
| 189 | +| Native library alignment issue | [native-android-16kb-alignment.md][native-android-16kb-alignment] | |
| 190 | + |
| 191 | +[references]: references/ |
| 192 | +[js-lists-flatlist-flashlist]: references/js-lists-flatlist-flashlist.md |
| 193 | +[js-profile-react]: references/js-profile-react.md |
| 194 | +[js-measure-fps]: references/js-measure-fps.md |
| 195 | +[js-memory-leaks]: references/js-memory-leaks.md |
| 196 | +[js-atomic-state]: references/js-atomic-state.md |
| 197 | +[js-concurrent-react]: references/js-concurrent-react.md |
| 198 | +[js-react-compiler]: references/js-react-compiler.md |
| 199 | +[js-animations-reanimated]: references/js-animations-reanimated.md |
| 200 | +[js-uncontrolled-components]: references/js-uncontrolled-components.md |
| 201 | +[native-turbo-modules]: references/native-turbo-modules.md |
| 202 | +[native-sdks-over-polyfills]: references/native-sdks-over-polyfills.md |
| 203 | +[native-measure-tti]: references/native-measure-tti.md |
| 204 | +[native-threading-model]: references/native-threading-model.md |
| 205 | +[native-profiling]: references/native-profiling.md |
| 206 | +[native-platform-setup]: references/native-platform-setup.md |
| 207 | +[native-view-flattening]: references/native-view-flattening.md |
| 208 | +[native-memory-patterns]: references/native-memory-patterns.md |
| 209 | +[native-memory-leaks]: references/native-memory-leaks.md |
| 210 | +[native-android-16kb-alignment]: references/native-android-16kb-alignment.md |
| 211 | +[bundle-barrel-exports]: references/bundle-barrel-exports.md |
| 212 | +[bundle-analyze-js]: references/bundle-analyze-js.md |
| 213 | +[bundle-tree-shaking]: references/bundle-tree-shaking.md |
| 214 | +[bundle-analyze-app]: references/bundle-analyze-app.md |
| 215 | +[bundle-r8-android]: references/bundle-r8-android.md |
| 216 | +[bundle-hermes-mmap]: references/bundle-hermes-mmap.md |
| 217 | +[bundle-native-assets]: references/bundle-native-assets.md |
| 218 | +[bundle-library-size]: references/bundle-library-size.md |
| 219 | +[bundle-code-splitting]: references/bundle-code-splitting.md |
| 220 | + |
| 221 | +## Attribution |
| 222 | + |
| 223 | +Based on "The Ultimate Guide to React Native Optimization" by Callstack. |
0 commit comments