optimising-expo-react-native-performance
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSummary
概述
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.
本技能将“应用感觉卡顿/迟缓”转化为一套针对Expo托管式React Native应用的可量化、可重复且可交付的优化方案。
核心准则:
- 针对用户可见的KPI进行优化(启动/首次交互时间、滚动帧率、导航响应速度、内存增长、95分位网络延迟)。
- 在类生产环境构建版本(release / profile / debugOptimized)中进行性能分析——禁止在开发模式下分析。
- 每次仅做一项修改,重新测量,并保留回滚路径。
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.
适用于以下需求:
- 修复启动缓慢、“白屏”或首次交互延迟问题。
- 修复滚动卡顿、丢帧、点击迟缓或过渡动画缓慢问题。
- 降低内存增长、压力下崩溃或图片/视频体积过大问题。
- 减小OTA更新包大小、JS bundle体积或Android安装包大小。
- 添加退化预防机制:性能预算 + CI门禁 + 生产环境监控。
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).
请勿在以下场景使用本技能:
- 对已流畅运行且无KPI退化的页面进行过早微优化。
- 在无可复现场景和基准数据的情况下修改代码。
- 盲目切换库来“优化”(先测量再行动)。
Inputs
输入信息
- Repo (Expo managed or CNG/prebuild), ideally with:
package.json- /
app.jsonapp.config.* - (if present)
metro.config.js babel.config.*- (if using EAS)
eas.json
- 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.
- 代码仓库(Expo托管或CNG/prebuild),理想情况下包含:
package.json- /
app.jsonapp.config.* - (若存在)
metro.config.js babel.config.*- (若使用EAS)
eas.json
- 具体的问题报告:
- 涉及的设备、操作系统版本,以及哪个流程感觉迟缓。
- 复现步骤(若使用Expo Router则提供页面名称)。
若信息缺失,尽可能从仓库中推断,并提出最小化复现脚本。
Outputs
输出结果
Deliver both:
- 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
- Code changes (PR-ready) implementing the top fixes, plus:
- Updated perf budgets (if needed)
- CI gate(s) for bundle/update size at minimum
需同时交付:
- 性能审计报告(参考中的模板):
assets/templates/perf-audit-report-template.md- KPI + 预算指标
- 基准测量数据(设备 + 构建类型)
- 根因假设 + 证据
- 修复计划(按投资回报率/风险排序)
- 优化前后的测量对比
- 代码变更(可直接提交PR):实现优先级最高的修复,同时包含:
- 更新后的性能预算(若需要)
- 至少针对bundle/更新包大小的CI门禁
Tooling assumptions
工具假设
You can use:
- Expo CLI (), EAS CLI (
npx expo …) where available.eas … - 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.
可使用以下工具:
- Expo CLI ()、EAS CLI (
npx expo …)(若可用)。eas … - React Native DevTools(Performance + Memory面板)用于JS层面分析。
- 原生性能分析工具(Android Studio、Xcode Instruments)用于CPU/内存/UI追踪。
优先选择:
- Release/profile构建版本进行测量。
- 优化前后使用同一设备类别和同一场景脚本。
The optimisation workflow (high level)
优化工作流(概览)
- Define KPIs + budgets (3–6 metrics max). Pick what users feel.
- Create a repeatable scenario (startup, list scroll, key navigation, etc.).
- Measure baseline in a production-like build.
- Classify the bottleneck domain:
- Startup/bundle
- JS thread
- UI thread
- Lists/images
- Memory
- Network/background
- Apply targeted fixes (smallest change, highest ROI first).
- Re-measure. Keep only changes with KPI wins.
- Add regression control (budgets + CI gates + monitoring).
- 定义KPI + 预算(最多3–6个指标)。选择用户能感知的指标。
- 创建可重复的测试场景(启动、列表滚动、关键导航等)。
- 在类生产构建版本中测量基准数据。
- 分类瓶颈领域:
- 启动/bundle
- JS线程
- UI线程
- 列表/图片
- 内存
- 网络/后台任务
- 应用定向修复(优先选择改动最小、投资回报率最高的方案)。
- 重新测量。仅保留能带来KPI提升的修改。
- 添加退化管控机制(预算 + CI门禁 + 监控)。
Detailed playbook
详细操作手册
Phase 0 — Establish reality (no guesswork)
阶段0 — 明确现状(拒绝猜测)
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.md0.3 Choose build type for measuring
- Prefer store-equivalent Release.
- If you need debuggability, use Android “profileable” builds, iOS Instruments, or Expo’s where applicable.
debugOptimized
0.1 确认版本与架构
- Expo SDK版本、React Native版本、React版本。
- New Architecture状态(新版本SDK中为必填)。
- JS引擎(Hermes/JSC/V8)、OTA更新使用情况()。
expo-updates - 主要性能敏感库:导航(Expo Router/React Navigation)、列表(FlashList)、动画(Reanimated)、图片()。
expo-image
0.2 选择KPI(选3–6个)
建议默认指标:
- 冷启动:首次渲染时间和/或首次交互时间
- 滚动:最重列表的丢帧率 / FPS
- 导航:代表性流程的95分位页面过渡时间
- 内存:重复导航循环5–10次后的稳态RSS
- 网络:关键接口的95分位延迟
将预算记录为具体数值(而非“快”)。参考。
references/00-principles-and-kpis.md0.3 选择用于测量的构建类型
- 优先选择与应用商店版本一致的Release版本。
- 若需要可调试性,使用Android“profileable”构建版本、iOS Instruments,或适用的Expo 版本。
debugOptimized
Phase 1 — Baseline measurement (release-build discipline)
阶段1 — 基准测量(严格遵循发布版本规范)
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.
1.1 基准检查清单(必须满足)
- 关闭开发模式。
- 禁用远程JS调试。
- 使用同一设备、同一操作系统版本、同一网络环境。
- 明确标注是热启动还是冷启动。
1.2 捕获追踪数据与数值
- React Native DevTools:
- 性能追踪(JS执行 + React追踪 + 网络事件)
- 堆快照(若怀疑内存问题)
- 原生工具:
- Android Studio System Trace用于卡顿归因
- Xcode Instruments(Time Profiler / Allocations / Leaks)
将原始产物(追踪文件、截图)与报告一起存储。
Phase 2 — Decide the bottleneck domain
阶段2 — 判断瓶颈领域
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.
使用以下判定规则:
- 启动缓慢:启动页时长过长、白屏、首次渲染延迟 → 启动/bundle领域。
- 点击延迟 / 过渡缓慢但滚动正常 → JS线程或导航领域。
- 滚动卡顿且JS任务量小 → UI线程或列表/渲染成本领域。
- 内存持续增长 → 内存泄漏 / 图片/视频压力领域。
- 所有操作等待API响应 → 网络/缓存领域。
Phase 3 — Apply high-ROI fixes by domain
阶段3 — 按领域应用高投资回报率修复方案
A) Startup & bundle
A) 启动与bundle
Do in this order:
- Stop doing work before first paint
- Gate only critical assets (fonts, tiny config) and hide splash ASAP.
- Confirm Hermes
- Make it explicit in app config if necessary.
- If you use OTA updates, ensure runtime compatibility when engine/bytecode changes.
- Shrink JS evaluation
- Prefer ESM imports, avoid breaking tree shaking.
- Consider Metro (validate side effects!).
inlineRequires
- Control OTA payloads
- Configure update asset inclusion/exclusion and verify assets.
- 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按以下顺序操作:
- 停止首次绘制前的非必要工作
- 仅加载关键资源(字体、小型配置)并尽快隐藏启动页。
- 确认启用Hermes
- 必要时在应用配置中明确声明。
- 若使用OTA更新,确保引擎/字节码变更时的运行时兼容性。
- 减少JS解析时间
- 优先使用ESM导入,避免破坏tree shaking。
- 考虑启用Metro (需验证副作用!)。
inlineRequires
- 管控OTA payload大小
- 配置更新资源的包含/排除规则并验证资源。
- Android体积优化选项(权衡测量)
- 启用R8混淆 + 资源压缩。
- 将bundle压缩视为可测量的开关(更小APK vs 更慢启动)。
参考。
references/02-startup-bundle-ota.mdB) JS thread stalls (renders + computation)
B) JS线程阻塞(渲染 + 计算)
High ROI:
- Remove production .
console.* - Defer heavy work with /
InteractionManager.requestAnimationFrame - 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高投资回报率方案:
- 移除生产环境中的语句。
console.* - 使用/
InteractionManager延迟繁重任务。requestAnimationFrame - 减少重渲染:
- 稳定props、拆分context、缓存高频行组件。
- 考虑使用React Compiler(分阶段发布 + 性能分析 + 易回滚)。
参考。
references/03-rendering-js-ui.mdC) UI thread / rendering / animations
C) UI线程 / 渲染 / 动画
High ROI:
- Prefer native-driven transitions (native stack / ).
react-native-screens - Avoid expensive UI operations on animated frames:
- Alpha compositing, heavy shadows, animating image size.
- Use native-driver animations where possible; for complex gestures prefer Reanimated worklets.
See .
references/03-rendering-js-ui.md高投资回报率方案:
- 优先使用原生驱动的过渡效果(native stack / )。
react-native-screens - 避免在动画帧上执行昂贵UI操作:
- Alpha合成、复杂阴影、图片尺寸动画。
- 尽可能使用原生驱动动画;复杂手势优先使用Reanimated worklets。
参考。
references/03-rendering-js-ui.mdD) Lists, images, and media
D) 列表、图片与媒体
High ROI:
- Fix list fundamentals:
- Stable keys, avoid re-render storms, tune render window.
- Add when item heights are known.
getItemLayout
- If still janky: evaluate FlashList for large/complex feeds.
- Move image-heavy UIs to with caching + placeholders.
expo-image - For replay-heavy video: use caching with a storage policy.
expo-video
See .
references/04-lists-images-media.md高投资回报率方案:
- 修复列表基础问题:
- 使用稳定key、避免重渲染风暴、调整渲染窗口。
- 若已知项高度,添加。
getItemLayout
- 若仍卡顿:针对大型/复杂信息流评估FlashList。
- 将图片密集型UI迁移到,并启用缓存 + 占位符。
expo-image - 针对频繁回放的视频:使用缓存并配置存储策略。
expo-video
参考。
references/04-lists-images-media.mdE) Memory leaks / pressure
E) 内存泄漏 / 内存压力
High ROI:
- Reproduce with a navigation stress loop.
- Take JS heap snapshots (before/after) to spot retained graphs.
- If JS heap stable but RSS grows: switch to native allocation tools.
See .
references/01-profiling-toolchain.md高投资回报率方案:
- 通过导航压力循环复现问题。
- 生成JS堆快照(前后对比)以识别内存保留图。
- 若JS堆稳定但RSS增长:切换到原生分配工具分析。
参考。
references/01-profiling-toolchain.mdF) Network & background work
F) 网络与后台任务
High ROI:
- Prevent refetch storms: cache + dedupe + prefetch.
- Use platform-appropriate background scheduling (best effort) for sync.
See .
references/05-network-background.md高投资回报率方案:
- 防止重复请求风暴:缓存 + 去重 + 预加载。
- 使用平台适配的后台调度机制(尽力而为)进行同步。
参考。
references/05-network-background.mdPhase 4 — Regression control (the “next level”)
阶段4 — 退化管控(进阶环节)
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最小可行退化管控:
- 提交预算文件(bundle大小 + 若干KPI阈值)。
- 设置CI门禁,在出现明显退化(bundle/更新包体积增长)时触发失败。
- 配置生产环境监控(崩溃 + 性能追踪)并启用符号化。
参考。
references/06-ci-regression.mdCommon 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.
- 在开发模式下进行基准测试并信任结果。
- 同时进行5项优化,却无法确定哪项起作用。
- “修复”症状(如延长启动页时长)而非根因(JS解析缓慢)。
- 未测量启动和运行时影响就启用体积优化开关(bundle压缩、激进压缩)。
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)
- 已选择KPI(3–6个)并记录预算
- 已在类生产构建版本中测量基准数据
- 已凭证据确定瓶颈领域
- 每次仅进行一项修复 + 记录优化前后数据
- 已添加至少一项退化门禁(bundle/更新包大小)
- 已配置监控(崩溃 + 性能)
References
参考资料
Start here:
references/00-principles-and-kpis.mdreferences/01-profiling-toolchain.mdreferences/02-startup-bundle-ota.mdreferences/03-rendering-js-ui.mdreferences/04-lists-images-media.mdreferences/06-ci-regression.md
External links: see .
references/resources.md从以下文件开始:
references/00-principles-and-kpis.mdreferences/01-profiling-toolchain.mdreferences/02-startup-bundle-ota.mdreferences/03-rendering-js-ui.mdreferences/04-lists-images-media.mdreferences/06-ci-regression.md
外部链接:参考。
references/resources.md