optimising-expo-react-native-performance

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.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "optimising-expo-react-native-performance" with this command: npx skills add tristanmanchester/agent-skills/tristanmanchester-agent-skills-optimising-expo-react-native-performance

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 skill forbids)

  • Benchmarking in dev mode and trusting the results.
  • Making 5 optimisations at once, then not knowing which mattered.
  • “Fixing” a symptom (e.g. bigger splash delay) instead of root cause (slow JS eval).
  • Turning on size flags (bundle compression, aggressive shrinking) without measuring startup and runtime.

Fast checklist

  • KPIs chosen (3–6) + budgets written down
  • Baseline measured in production-like build
  • Bottleneck domain identified with evidence
  • One fix at a time + before/after numbers
  • At least one regression gate added (bundle/update size)
  • Monitoring configured (crash + perf)

References

Start here:

  • references/00-principles-and-kpis.md
  • references/01-profiling-toolchain.md
  • references/02-startup-bundle-ota.md
  • references/03-rendering-js-ui.md
  • references/04-lists-images-media.md
  • references/06-ci-regression.md

External links: see references/resources.md.

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Automation

designing-beautiful-websites

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

reddit-readonly

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

styling-nativewind-v4-expo

No summary provided by upstream source.

Repository SourceNeeds Review