React Performance Auditing
| Field | Value |
|---|---|
| Type | Skill Resource |
| Source | ~/.copilot/skills/frontend/references/react-perf.md |
| Description | Not specified |
Source Content
React Performance Auditing
Audit a React app for performance regressions with Lighthouse, react-scan render heatmaps, bundle inspection, and CrUX/RUM field data — then lock the wins in with a CI perf budget. Absorbed from the former react-perf-auditor skill.
Use for
- Users report sluggishness or a specific slow interaction.
- Web Vitals (LCP, INP, CLS) regressed in production.
- Pre-launch sweep before a feature, marketing push, or major release.
- Quarterly preventive audit.
How it works
- Baseline.
npx lighthouse <url> --preset=desktop --output=json --output=htmlagainst production. Capture LCP, INP, CLS, TBT, total bytes. - Render hotspots. Run react-scan in dev, exercise key flows, screenshot heatmap. Flag any component re-rendering >5×/interaction.
- Bundle analysis.
vite build --mode=analyze(rollup-plugin-visualizer) ornpx source-map-explorer. Top 10 modules by size; flag any >50KB gzipped chunk not lazy-loaded. - Image audit. Every
<img>not AVIF/WebP, missingloading="lazy", missingwidth/height, or oversized → fix list. - Network audit. DevTools Performance tab; serial waterfalls → batch with TanStack Query or hoist to a Router loader.
- State audit.
useStatethat should be URL state; Context providers wrapping >50% of the tree (should be Zustand); prop drilling >3 levels. - Prioritize. Score each finding
estimated_ms_saved / hours_to_fix. Top 5 first. - Fix and re-measure. Implement, re-run Lighthouse, verify Web Vitals improvement.
- Lock it in. Add
bundlewatchorsize-limitto CI with budgets matching the new baseline. Optional Playwright perf test asserting LCP < target.
Examples
- “Users say the dashboard feels slow” → baseline with Lighthouse on prod, run react-scan against the dashboard flow, and return a ranked top-5 with measured ms-saved per fix.
- “Our LCP regressed from 1.8s to 3.4s — find it” → diff the bundle against the last release, audit hero images for missing
width/height/AVIF, and check for a new render-blocking script. - “Before we launch, do a perf sweep” → run the full audit (Lighthouse + react-scan + bundle + image + network + state), implement the top 5 fixes, re-measure, and wire
size-limitinto CI at the new baseline. - “Should I memo all these components?” → no —
React.memoafter a profiler trace, not before. Show the trace first.
Quick wins to check first
React.lazyfor routes off the critical path.loading="lazy",width/height, AVIF/WebP for below-fold images.- Virtualization (TanStack Virtual) for any list >100 items.
useDeferredValuefor input-driven heavy renders.- Drop dead imports — many “wins” are ghost dependencies.
Self-rubric
- Numbers, not vibes. Every finding has a measured ms / KB / count.
- Ranked by leverage. Top 5 are the highest
ms_saved / hours_to_fix, not the easiest. - Re-measured after fixes. Lighthouse re-run, delta reported.
- CI guard added. A budget exists so the regression can’t sneak back.
- No premature
memo. Memoization is justified by a profiler trace. - Web Vitals named. Wins map to LCP / INP / CLS, not just “feels faster”.
- Validated:
scripts/check_perf_report.sh REPORT.md [REPO_ROOT]exits 0.
scripts/check_perf_report.sh REPORT.md [REPO_ROOT] fails if the report has no real before/after numeric comparison (a number with a unit — ms/KB/MB/fps/s — near before/after language), or if it references a CI perf budget file (e.g. budget.json, .bundlesizerc, lighthouserc*) that doesn’t actually exist on disk.
References
- Web Vitals — Core Web Vitals thresholds.
- react-scan — render heatmap.
- size-limit — bundle budget for CI.
- TanStack Virtual — list virtualization.
- WebPageTest — real-network perf testing. </content>