Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
a8eb9df
included currency among the keys in fuse option, allow search with cu…
azeez1776 Apr 24, 2023
3ab5866
Merge branch 'master' of github.com:xcarpentier/react-native-country-…
Abramovick Jan 19, 2026
3a6251e
Update ESLint configuration, upgrade dependencies, and enhance testin…
Abramovick Jan 20, 2026
281e0bd
Enhance country search functionality and improve modal behavior
Abramovick Jan 20, 2026
7f41075
Add prepare script to package.json for build process
Abramovick Jan 20, 2026
0d0148f
Refactor build script in package.json and optimize CountryModal compo…
Abramovick Jan 20, 2026
c9114d7
Update build process in package.json and add tsconfig.build.json
Abramovick Jan 20, 2026
b77a343
Add React Native best practices documentation and references
Abramovick Jan 20, 2026
ffab455
Enhance ESLint configuration, update dependencies, and add example app
Abramovick Jan 25, 2026
a261fd8
Add modal functionality to country picker screens
Abramovick Jan 25, 2026
1cdcf21
Update filtering screen text and remove unused flatListProps
Abramovick Jan 25, 2026
4401d2c
Enhance country picker functionality and update dependencies
Abramovick Jan 26, 2026
c11f093
Add Swahili translations and update language codes in country data
Abramovick Jan 26, 2026
e936950
Refactor country picker integration and remove unused settings hook
Abramovick Jan 26, 2026
10ec956
Enhance theming implementation in CountryTheme.ts
Abramovick Jan 26, 2026
204735b
Refactor configuration files and update dependencies
Abramovick Jan 26, 2026
3a84d82
Remove mock implementation of react-async-hook from test files
Abramovick Jan 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
182 changes: 182 additions & 0 deletions .claude/skills/react-native-best-practices/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
---
name: react-native-best-practices
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.
license: MIT
metadata:
author: Callstack
tags: react-native, expo, performance, optimization, profiling
---

# React Native Best Practices

## Overview

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".

## Skill Format

Each reference file follows a hybrid format for fast lookup and deep understanding:

- **Quick Pattern**: Incorrect/Correct code snippets for immediate pattern matching
- **Quick Command**: Shell commands for process/measurement skills
- **Quick Config**: Configuration snippets for setup-focused skills
- **Quick Reference**: Summary tables for conceptual skills
- **Deep Dive**: Full context with When to Use, Prerequisites, Step-by-Step, Common Pitfalls

**Impact ratings**: CRITICAL (fix immediately), HIGH (significant improvement), MEDIUM (worthwhile optimization)

## When to Apply

Reference these guidelines when:
- Debugging slow/janky UI or animations
- Investigating memory leaks (JS or native)
- Optimizing app startup time (TTI)
- Reducing bundle or app size
- Writing native modules (Turbo Modules)
- Profiling React Native performance
- Reviewing React Native code for performance

## Priority-Ordered Guidelines

| Priority | Category | Impact | Prefix |
|----------|----------|--------|--------|
| 1 | FPS & Re-renders | CRITICAL | `js-*` |
| 2 | Bundle Size | CRITICAL | `bundle-*` |
| 3 | TTI Optimization | HIGH | `native-*`, `bundle-*` |
| 4 | Native Performance | HIGH | `native-*` |
| 5 | Memory Management | MEDIUM-HIGH | `js-*`, `native-*` |
| 6 | Animations | MEDIUM | `js-*` |

## Quick Reference

### Critical: FPS & Re-renders

**Profile first:**
```bash
# Open React Native DevTools
# Press 'j' in Metro, or shake device → "Open DevTools"
```

**Common fixes:**
- Replace ScrollView with FlatList/FlashList for lists
- Use React Compiler for automatic memoization
- Use atomic state (Jotai/Zustand) to reduce re-renders
- Use `useDeferredValue` for expensive computations

### Critical: Bundle Size

**Analyze bundle:**
```bash
npx react-native bundle \
--entry-file index.js \
--bundle-output output.js \
--platform ios \
--sourcemap-output output.js.map \
--dev false --minify true

npx source-map-explorer output.js --no-border-checks
```

**Common fixes:**
- Avoid barrel imports (import directly from source)
- Remove unnecessary Intl polyfills (Hermes has native support)
- Enable tree shaking (Expo SDK 52+ or Re.Pack)
- Enable R8 for Android native code shrinking

### High: TTI Optimization

**Measure TTI:**
- Use `react-native-performance` for markers
- Only measure cold starts (exclude warm/hot/prewarm)

**Common fixes:**
- Disable JS bundle compression on Android (enables Hermes mmap)
- Use native navigation (react-native-screens)
- Defer non-critical work with `InteractionManager`

### High: Native Performance

**Profile native:**
- iOS: Xcode Instruments → Time Profiler
- Android: Android Studio → CPU Profiler

**Common fixes:**
- Use background threads for heavy native work
- Prefer async over sync Turbo Module methods
- Use C++ for cross-platform performance-critical code

## References

Full documentation with code examples in `references/`:

### JavaScript/React (`js-*`)

| File | Impact | Description |
|------|--------|-------------|
| `js-lists-flatlist-flashlist.md` | CRITICAL | Replace ScrollView with virtualized lists |
| `js-profile-react.md` | MEDIUM | React DevTools profiling |
| `js-measure-fps.md` | HIGH | FPS monitoring and measurement |
| `js-memory-leaks.md` | MEDIUM | JS memory leak hunting |
| `js-atomic-state.md` | HIGH | Jotai/Zustand patterns |
| `js-concurrent-react.md` | HIGH | useDeferredValue, useTransition |
| `js-react-compiler.md` | HIGH | Automatic memoization |
| `js-animations-reanimated.md` | MEDIUM | Reanimated worklets |
| `js-uncontrolled-components.md` | HIGH | TextInput optimization |

### Native (`native-*`)

| File | Impact | Description |
|------|--------|-------------|
| `native-turbo-modules.md` | HIGH | Building fast native modules |
| `native-sdks-over-polyfills.md` | HIGH | Native vs JS libraries |
| `native-measure-tti.md` | HIGH | TTI measurement setup |
| `native-threading-model.md` | HIGH | Turbo Module threads |
| `native-profiling.md` | MEDIUM | Xcode/Android Studio profiling |
| `native-platform-setup.md` | MEDIUM | iOS/Android tooling guide |
| `native-view-flattening.md` | MEDIUM | View hierarchy debugging |
| `native-memory-patterns.md` | MEDIUM | C++/Swift/Kotlin memory |
| `native-memory-leaks.md` | MEDIUM | Native memory leak hunting |

### Bundling (`bundle-*`)

| File | Impact | Description |
|------|--------|-------------|
| `bundle-barrel-exports.md` | CRITICAL | Avoid barrel imports |
| `bundle-analyze-js.md` | CRITICAL | JS bundle visualization |
| `bundle-tree-shaking.md` | HIGH | Dead code elimination |
| `bundle-analyze-app.md` | HIGH | App size analysis |
| `bundle-r8-android.md` | HIGH | Android code shrinking |
| `bundle-hermes-mmap.md` | HIGH | Disable bundle compression |
| `bundle-native-assets.md` | HIGH | Asset catalog setup |
| `bundle-library-size.md` | MEDIUM | Evaluate dependencies |
| `bundle-code-splitting.md` | MEDIUM | Re.Pack code splitting |

## Searching References

```bash
# Find patterns by keyword
grep -l "reanimated" references/
grep -l "flatlist" references/
grep -l "memory" references/
grep -l "profil" references/
grep -l "tti" references/
grep -l "bundle" references/
```

## Problem → Skill Mapping

| Problem | Start With |
|---------|------------|
| App feels slow/janky | `js-measure-fps.md` → `js-profile-react.md` |
| Too many re-renders | `js-profile-react.md` → `js-react-compiler.md` |
| Slow startup (TTI) | `native-measure-tti.md` → `bundle-analyze-js.md` |
| Large app size | `bundle-analyze-app.md` → `bundle-r8-android.md` |
| Memory growing | `js-memory-leaks.md` or `native-memory-leaks.md` |
| Animation drops frames | `js-animations-reanimated.md` |
| List scroll jank | `js-lists-flatlist-flashlist.md` |
| TextInput lag | `js-uncontrolled-components.md` |
| Native module slow | `native-turbo-modules.md` → `native-threading-model.md` |

## Attribution

Based on "The Ultimate Guide to React Native Optimization" by Callstack.
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
---
title: Analyze App Bundle Size
impact: HIGH
tags: app-size, ruler, emerge-tools, thinning
---

# Skill: Analyze App Bundle Size

Measure iOS and Android app download/install sizes using Ruler, App Store Connect, and Emerge Tools.

## Quick Command

```bash
# Android (Ruler)
cd android && ./gradlew analyzeReleaseBundle

# iOS (Xcode export with thinning)
cd ios && xcodebuild -exportArchive \
-archivePath MyApp.xcarchive \
-exportPath ./export \
-exportOptionsPlist ExportOptions.plist
# Check: App Thinning Size Report.txt
```

## When to Use

- App download size is too large
- Users complain about storage usage
- App approaching store limits
- Comparing releases for size regression

> **Note**: This skill involves interpreting visual size reports (Ruler, Emerge Tools X-Ray). AI agents cannot yet process screenshots autonomously. Use this as a guide while reviewing the reports manually, or await MCP-based visual feedback integration (see roadmap).

## Key Metrics

| Metric | Description | User Impact |
|--------|-------------|-------------|
| Download Size | Compressed, transferred over network | Download time, data usage |
| Install Size | Uncompressed, on device storage | Storage space |

**Google finding**: Every 6 MB increase reduces installs by 1%.

## Android: Ruler (Spotify)

### Setup

Add to `android/build.gradle`:

```groovy
buildscript {
dependencies {
classpath("com.spotify.ruler:ruler-gradle-plugin:2.0.0-beta-3")
}
}
```

Add to `android/app/build.gradle`:

```groovy
apply plugin: "com.spotify.ruler"

ruler {
abi.set("arm64-v8a") // Target architecture
locale.set("en")
screenDensity.set(480)
sdkVersion.set(34)
}
```

### Analyze

```bash
cd android
./gradlew analyzeReleaseBundle
```

Opens HTML report with:
- Download size
- Install size
- Component breakdown (biggest → smallest)

### CI Size Validation

```groovy
ruler {
verification {
downloadSizeThreshold = 20 * 1024 * 1024 // 20 MB
installSizeThreshold = 50 * 1024 * 1024 // 50 MB
}
}
```

Build fails if thresholds exceeded.

## iOS: Xcode App Thinning

### Via App Store Connect (Most Accurate)

After uploading to TestFlight:
1. Open App Store Connect
2. Go to your build
3. View size table by device variant

**Note**: TestFlight builds include debug data, App Store builds slightly larger due to DRM.

### Via Xcode Export

1. Archive app: **Product → Archive**
2. In Organizer, click **Distribute App**
3. Select **Custom**
4. Choose **App Thinning: All compatible device variants**

Or in `ExportOptions.plist`:

```xml
<key>thinning</key>
<string>&lt;thin-for-all-variants&gt;</string>
```

### Output

Creates folder with:
- **Universal IPA**: All variants combined
- **Thinned IPAs**: One per device variant
- **App Thinning Size Report.txt**:

```
Variant: SampleApp-<UUID>.ipa
App + On Demand Resources size: 3.5 MB compressed, 10.6 MB uncompressed
App size: 3.5 MB compressed, 10.6 MB uncompressed
```

- Compressed = Download size
- Uncompressed = Install size

## Emerge Tools (Cross-Platform)

Third-party service with visual analysis.

### Upload

Upload IPA, APK, or AAB through their web interface or CI integration.

### Features

![Emerge Tools X-Ray for iOS](images/emerge-xray-ios.png)

- **X-Ray**: Treemap visualization (like source-map-explorer for binaries)
- Shows Frameworks (hermes.framework), Mach-O sections (TEXT, DATA), etc.
- Color-coded: Binaries, Localizations, Fonts, Asset Catalogs, Videos, CoreML Models
- Visible components: `main.jsbundle` (JS code), RCT modules, DYLD sections
- **Breakdown**: Component-by-component size
- **Insights**: Automated suggestions (use with caution)

**Caution**: Some suggestions may not apply to React Native (e.g., "remove Hermes").

## Size Comparison

| Tool | Platform | Accuracy | CI Integration |
|------|----------|----------|----------------|
| Ruler | Android | High | Yes (Gradle) |
| App Store Connect | iOS | Highest | No |
| Xcode Export | iOS | High | Yes (xcodebuild) |
| Emerge Tools | Both | High | Yes (API) |

## Typical React Native App Sizes

| Component | Approximate Size |
|-----------|------------------|
| Hermes engine | ~2-3 MB |
| React Native core | ~3-5 MB |
| JavaScript bundle | 1-10 MB |
| Assets (images, etc.) | Varies |

**Baseline empty app**: ~6-10 MB download

## Optimization Impact Example

| Optimization | Size Reduction |
|--------------|----------------|
| Enable R8 (Android) | ~30% |
| Remove unused polyfills | 400+ KB |
| Asset catalog (iOS) | 10-50% of assets |
| Tree shaking | 10-15% |

## Quick Commands

```bash
# Android release bundle size
cd android && ./gradlew bundleRelease
# Check: android/app/build/outputs/bundle/release/

# iOS archive
cd ios && xcodebuild -workspace ios/MyApp.xcworkspace \
-scheme MyApp \
-configuration Release \
-archivePath MyApp.xcarchive \
archive

# Export with thinning report
cd ios && xcodebuild -exportArchive \
-archivePath MyApp.xcarchive \
-exportPath ./export \
-exportOptionsPlist ExportOptions.plist
```

## Related Skills

- [bundle-r8-android.md](./bundle-r8-android.md) - Reduce Android size
- [bundle-native-assets.md](./bundle-native-assets.md) - Optimize asset delivery
- [bundle-analyze-js.md](./bundle-analyze-js.md) - JS bundle analysis
Loading