React / Vite Performance Reviewer
Review [[diff]] for web performance issues. Use [[context]] when provided.
Load references/PERFORMANCE_CHECKLIST.md and apply all sections relevant to the changed files.
Use assets/review-report-template.md for the full structured report.
Severity classification
| Severity |
Meaning |
critical |
Browser OOM crash, hang, or complete render failure under normal traffic |
high |
Visible jank or +1s LCP/TTI regression under moderate load (slow 4G) |
medium |
Degrades experience on low-end devices or under high traffic (50+ concurrent users) |
low |
Minor inefficiency, acceptable now but risky at scale |
info |
Observation with no current risk |
Detection rules
Rendering
- Flag components re-rendering on every parent render when props haven't changed — check for
React.memo absence.
- Flag inline function/object/array props in JSX producing a new reference each render.
- Flag
useEffect with unstable dependencies.
- Flag Context providers whose
value is a new object on every render.
- Flag deeply nested context consumers subscribing to a large context object when only one field is needed.
- Flag
key changes on list items that are not actually replaced.
Memory leaks
- Flag event listeners, timers, and subscriptions registered in
useEffect without cleanup.
- Flag ResizeObserver, IntersectionObserver, and MutationObserver not disconnected on unmount.
- Flag large data structures (chart datasets, blob URLs, canvas references) not released on unmount.
State management
- Flag selectors returning new object/array references on every store update.
- Flag excessive global state for transient UI concerns (hover, focus, scroll position).
- Flag derived state recalculated on every render that should live in
useMemo or a selector.
Bundle & build
- Flag imports pulling in the full package rather than tree-shaken named exports.
- Flag large libraries with smaller alternatives for the actual usage.
- Flag components loading synchronously at route level but only conditionally visible.
- Flag Vite config without
manualChunks for large vendor dependency groups.
- Flag assets served without content hashes.
- Flag
console.log calls not removed in production build.
- Flag third-party scripts loaded synchronously in
<head> rather than deferred.
Network & caching
- Flag
fetch/axios calls in useEffect without AbortController cleanup.
- Flag the same endpoint fetched in multiple sibling components without shared query-key deduplication.
- Flag missing
staleTime on React Query queries that don't need fresh data on every mount.
- Flag responses >100KB without pagination, field selection, or compression.
- Flag polling without backoff or visibility-aware pausing (
document.hidden).
- Flag absence of retry logic with exponential backoff on transient errors.
Assets
- Flag
<img> without width/height attributes (causes CLS).
- Flag images not using modern formats (WebP, AVIF) or missing
srcset.
- Flag render-blocking fonts without
font-display: swap or preload hints.
- Flag SVGs inlined in list/table items.
List & table rendering
- Flag tables rendering >100 rows without windowing (TanStack Virtual, react-window).
- Flag infinite scroll implementations that accumulate DOM nodes rather than virtualizing.
- Flag
document.querySelector in React event handlers — use useRef.
- Flag layout reads (
offsetHeight, getBoundingClientRect) interleaved with DOM writes (layout thrashing).
Startup & LCP
- Flag heavy imports at app root only needed on a specific route.
- Flag third-party analytics scripts loaded synchronously in
<head>.
- Flag missing
<link rel="preload"> for the LCP candidate image.
Gotchas
- Vite dev mode does not tree-shake — always validate bundle impact on a production build.
- React 18 Strict Mode double-invokes effects in development — do not rely on dev behavior to confirm cleanup correctness.
useCallback/useMemo have a cost — flag only when re-render cost is measurable.
- Context re-renders propagate synchronously — a Provider high in the tree with a frequently updated value can silently re-render expensive subtrees.
VITE_* env vars are inlined at build time — secrets must never be placed in VITE_* vars.
Output format
For each finding:
Finding: <short title>
Severity: critical | high | medium | low | info
Location: <file path>:<line range or function name>
Risk: <what breaks, when, under what traffic/device condition>
Failure mode: <observable symptom — jank, OOM, slow LCP, layout shift, network waterfall>
Fix: <concrete change with code snippet if useful>
Verification: <how to confirm — bundle analysis, profiler, Lighthouse>
Order findings by severity descending.
Constraints
- Read-only unless the user explicitly asks for fixes.
- Do not flag style-only issues or micro-optimizations with no measurable impact.
- Validate findings against the current file state — do not hallucinate line numbers.
1---2name: react-vite-performance-reviewer-23description: Review React and Vite web app code for browser performance, memory usage, bundle size, rendering speed, network cost, and behavior under high traffic, slow devices, and large datasets. Detects re-renders, memory leaks, large bundle growth, over-fetching, layout thrashing, and weak error/retry behavior.4---56# React / Vite Performance Reviewer78Review `[[diff]]` for web performance issues. Use `[[context]]` when provided.910Load `references/PERFORMANCE_CHECKLIST.md` and apply all sections relevant to the changed files.11Use `assets/review-report-template.md` for the full structured report.1213## Severity classification1415| Severity | Meaning |16|----------|---------|17| `critical` | Browser OOM crash, hang, or complete render failure under normal traffic |18| `high` | Visible jank or +1s LCP/TTI regression under moderate load (slow 4G) |19| `medium` | Degrades experience on low-end devices or under high traffic (50+ concurrent users) |20| `low` | Minor inefficiency, acceptable now but risky at scale |21| `info` | Observation with no current risk |2223## Detection rules2425### Rendering26- Flag components re-rendering on every parent render when props haven't changed — check for `React.memo` absence.27- Flag inline function/object/array props in JSX producing a new reference each render.28- Flag `useEffect` with unstable dependencies.29- Flag Context providers whose `value` is a new object on every render.30- Flag deeply nested context consumers subscribing to a large context object when only one field is needed.31- Flag `key` changes on list items that are not actually replaced.3233### Memory leaks34- Flag event listeners, timers, and subscriptions registered in `useEffect` without cleanup.35- Flag ResizeObserver, IntersectionObserver, and MutationObserver not disconnected on unmount.36- Flag large data structures (chart datasets, blob URLs, canvas references) not released on unmount.3738### State management39- Flag selectors returning new object/array references on every store update.40- Flag excessive global state for transient UI concerns (hover, focus, scroll position).41- Flag derived state recalculated on every render that should live in `useMemo` or a selector.4243### Bundle & build44- Flag imports pulling in the full package rather than tree-shaken named exports.45- Flag large libraries with smaller alternatives for the actual usage.46- Flag components loading synchronously at route level but only conditionally visible.47- Flag Vite config without `manualChunks` for large vendor dependency groups.48- Flag assets served without content hashes.49- Flag `console.log` calls not removed in production build.50- Flag third-party scripts loaded synchronously in `<head>` rather than deferred.5152### Network & caching53- Flag `fetch`/`axios` calls in `useEffect` without `AbortController` cleanup.54- Flag the same endpoint fetched in multiple sibling components without shared query-key deduplication.55- Flag missing `staleTime` on React Query queries that don't need fresh data on every mount.56- Flag responses >100KB without pagination, field selection, or compression.57- Flag polling without backoff or visibility-aware pausing (`document.hidden`).58- Flag absence of retry logic with exponential backoff on transient errors.5960### Assets61- Flag `<img>` without `width`/`height` attributes (causes CLS).62- Flag images not using modern formats (WebP, AVIF) or missing `srcset`.63- Flag render-blocking fonts without `font-display: swap` or preload hints.64- Flag SVGs inlined in list/table items.6566### List & table rendering67- Flag tables rendering >100 rows without windowing (TanStack Virtual, react-window).68- Flag infinite scroll implementations that accumulate DOM nodes rather than virtualizing.69- Flag `document.querySelector` in React event handlers — use `useRef`.70- Flag layout reads (`offsetHeight`, `getBoundingClientRect`) interleaved with DOM writes (layout thrashing).7172### Startup & LCP73- Flag heavy imports at app root only needed on a specific route.74- Flag third-party analytics scripts loaded synchronously in `<head>`.75- Flag missing `<link rel="preload">` for the LCP candidate image.7677## Gotchas7879- Vite dev mode does not tree-shake — always validate bundle impact on a production build.80- React 18 Strict Mode double-invokes effects in development — do not rely on dev behavior to confirm cleanup correctness.81- `useCallback`/`useMemo` have a cost — flag only when re-render cost is measurable.82- Context re-renders propagate synchronously — a Provider high in the tree with a frequently updated value can silently re-render expensive subtrees.83- `VITE_*` env vars are inlined at build time — secrets must never be placed in `VITE_*` vars.8485## Output format8687For each finding:8889```90Finding: <short title>91Severity: critical | high | medium | low | info92Location: <file path>:<line range or function name>93Risk: <what breaks, when, under what traffic/device condition>94Failure mode: <observable symptom — jank, OOM, slow LCP, layout shift, network waterfall>95Fix: <concrete change with code snippet if useful>96Verification: <how to confirm — bundle analysis, profiler, Lighthouse>97```9899Order findings by severity descending.100101## Constraints102103- Read-only unless the user explicitly asks for fixes.104- Do not flag style-only issues or micro-optimizations with no measurable impact.105- Validate findings against the current file state — do not hallucinate line numbers.