Claude
Skills
Sign in
Back

optimising-expo-react-native-performance

Included with Lifetime
$97 forever

Diagnose, improve, and prevent performance regressions in Expo-based React Native apps using release-build profiling, KPI budgets, and targeted fixes across startup, rendering, lists, images, memory, and networking.

Web Devreact-nativeexpoperformanceprofilingoptimisationhermesmetroflashlistscriptsassets

What this skill does


## Summary

This skill turns “the app feels slow/janky” into a **measured**, **repeatable**, and **shippable** optimisation program for Expo-managed React Native apps.

Non‑negotiables:
- Optimise against **user-visible KPIs** (startup/TTI, scroll FPS, navigation responsiveness, memory growth, p95 network latency).
- Profile in **production-like builds** (release / profile / debugOptimized) — **not** in dev mode.
- Make **one change at a time**, re-measure, and keep a rollback path.

## When to use

Use when you need to:
- Fix **slow startup**, “white screen”, or delayed time-to-interactive.
- Fix **scroll jank**, dropped frames, sluggish taps, or slow transitions.
- Reduce **memory growth**, crashes under pressure, or image/video bloat.
- Reduce **OTA update size**, JS bundle size, or Android binary size.
- Add **regression prevention**: perf budgets + CI gates + production monitoring.

## When NOT to use

Don’t use this skill to:
- Prematurely micro-optimise already-smooth screens with no KPI regression.
- Make changes without a reproducible scenario and a baseline.
- “Optimise” by switching libraries blindly (measure first).

## Inputs

- Repo (Expo managed or CNG/prebuild), ideally with:
  - `package.json`
  - `app.json` / `app.config.*`
  - `metro.config.js` (if present)
  - `babel.config.*`
  - `eas.json` (if using EAS)
- A concrete report of the problem:
  - Device(s), OS versions, and which flow feels slow.
  - Steps to reproduce (or a screen name if using Expo Router).

If details are missing, infer as much as possible from the repo and propose a minimal repro script.

## Outputs

Deliver **both**:
1) **Perf audit report** (see template in `assets/templates/perf-audit-report-template.md`):
   - KPIs + budgets
   - Baseline measurements (device + build type)
   - Root cause hypothesis + evidence
   - Fix plan (ordered by ROI / risk)
   - Before/after measurements
2) **Code changes** (PR-ready) implementing the top fixes, plus:
   - Updated perf budgets (if needed)
   - CI gate(s) for bundle/update size at minimum

## Tooling assumptions

You can use:
- Expo CLI (`npx expo …`), EAS CLI (`eas …`) where available.
- React Native DevTools (Performance + Memory panels) for JS-level analysis.
- Native profilers (Android Studio, Xcode Instruments) for CPU/memory/UI tracing.

You should prefer:
- **Release/profile builds** for measurement.
- **Same device class** and **same scenario script** for before/after.

## The optimisation workflow (high level)

1) **Define KPIs + budgets** (3–6 metrics max). Pick what users feel.
2) **Create a repeatable scenario** (startup, list scroll, key navigation, etc.).
3) **Measure baseline in a production-like build**.
4) **Classify the bottleneck domain**:
   - Startup/bundle
   - JS thread
   - UI thread
   - Lists/images
   - Memory
   - Network/background
5) Apply **targeted fixes** (smallest change, highest ROI first).
6) **Re-measure**. Keep only changes with KPI wins.
7) Add **regression control** (budgets + CI gates + monitoring).

## Detailed playbook

### Phase 0 — Establish reality (no guesswork)

**0.1 Identify versions and architecture**
- Expo SDK version, React Native version, React version.
- New Architecture status (mandatory in newer SDKs).
- JS engine (Hermes/JSC/V8), OTA updates usage (`expo-updates`).
- Major perf-sensitive libs: navigation (Expo Router/React Navigation), lists (FlashList), animation (Reanimated), images (`expo-image`).

**0.2 Choose KPIs (pick 3–6)**
Suggested defaults:
- Cold start: **time-to-first-render** and/or **time-to-interactive**
- Scroll: dropped frames / FPS on the heaviest list
- Navigation: p95 screen transition time for a representative flow
- Memory: steady-state RSS after repeating a navigation loop 5–10×
- Network: p95 API latency on a key endpoint

Record budgets as numbers (not “fast”). See `references/00-principles-and-kpis.md`.

**0.3 Choose build type for measuring**
- Prefer store-equivalent **Release**.
- If you need debuggability, use Android “profileable” builds, iOS Instruments, or Expo’s `debugOptimized` where applicable.

### Phase 1 — Baseline measurement (release-build discipline)

**1.1 Baseline checklist (must pass)**
- Dev mode off.
- No remote JS debugging.
- Same device, same OS version, same network conditions.
- Warm vs cold start explicitly noted.

**1.2 Capture traces and numbers**
- React Native DevTools:
  - Performance trace (JS execution + React tracks + network events)
  - Heap snapshot (if memory suspected)
- Native tools:
  - Android Studio System Trace for jank attribution
  - Xcode Instruments (Time Profiler / Allocations / Leaks)

Store raw artefacts (trace files, screenshots) alongside your report.

### Phase 2 — Decide the bottleneck domain

Use this decision rubric:
- **Startup slow**: long splash, white screen, slow first render → startup/bundle.
- **Taps lag / transitions slow** but scrolling OK → JS thread or navigation.
- **Scroll stutters** even with little JS work → UI thread or list/render cost.
- **Memory climbs over time** → leak / image/video pressure.
- **Everything waits on API** → network/caching.

### Phase 3 — Apply high-ROI fixes by domain

#### A) Startup & bundle
Do in this order:
1) **Stop doing work before first paint**
   - Gate only critical assets (fonts, tiny config) and hide splash ASAP.
2) **Confirm Hermes**
   - Make it explicit in app config if necessary.
   - If you use OTA updates, ensure runtime compatibility when engine/bytecode changes.
3) **Shrink JS evaluation**
   - Prefer ESM imports, avoid breaking tree shaking.
   - Consider Metro `inlineRequires` (validate side effects!).
4) **Control OTA payloads**
   - Configure update asset inclusion/exclusion and verify assets.
5) **Android size knobs (measure trade-offs)**
   - Enable R8 minify + resource shrinking.
   - Treat bundle compression as a measured toggle (smaller APK vs slower startup).

See `references/02-startup-bundle-ota.md`.

#### B) JS thread stalls (renders + computation)
High ROI:
1) Remove production `console.*`.
2) Defer heavy work with `InteractionManager` / `requestAnimationFrame`.
3) Reduce re-renders:
   - Stabilise props, split context, memoise hot rows.
   - Consider **React Compiler** (branch rollout + profiling + easy rollback).

See `references/03-rendering-js-ui.md`.

#### C) UI thread / rendering / animations
High ROI:
1) Prefer native-driven transitions (native stack / `react-native-screens`).
2) Avoid expensive UI operations on animated frames:
   - Alpha compositing, heavy shadows, animating image size.
3) Use native-driver animations where possible; for complex gestures prefer Reanimated worklets.

See `references/03-rendering-js-ui.md`.

#### D) Lists, images, and media
High ROI:
1) Fix list fundamentals:
   - Stable keys, avoid re-render storms, tune render window.
   - Add `getItemLayout` when item heights are known.
2) If still janky: evaluate FlashList for large/complex feeds.
3) Move image-heavy UIs to `expo-image` with caching + placeholders.
4) For replay-heavy video: use `expo-video` caching with a storage policy.

See `references/04-lists-images-media.md`.

#### E) Memory leaks / pressure
High ROI:
1) Reproduce with a navigation stress loop.
2) Take JS heap snapshots (before/after) to spot retained graphs.
3) If JS heap stable but RSS grows: switch to native allocation tools.

See `references/01-profiling-toolchain.md`.

#### F) Network & background work
High ROI:
1) Prevent refetch storms: cache + dedupe + prefetch.
2) Use platform-appropriate background scheduling (best effort) for sync.

See `references/05-network-background.md`.

### Phase 4 — Regression control (the “next level”)

Minimum viable regression control:
- **Budget file** committed (bundle size + a few KPI thresholds).
- **CI gate** that fails on obvious regressions (bundle/update size growth).
- **Production monitoring** (crash + perf traces) with symbolication.

See `references/06-ci-regression.md`.

## Common pitfalls (things this 

Related in Web Dev