name: vercel-react-best-practices description: React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements. license: MIT metadata: author: vercel version: "1.0.0"
Vercel React Best Practices
Comprehensive performance optimization guide for React and Next.js applications, maintained by Vercel. Contains 58 rules across 8 categories, prioritized by impact to guide automated refactoring and code generation.
When to Apply
Reference these guidelines when:
- Writing new React components or Next.js pages
- Implementing data fetching (client or server-side)
- Reviewing code for performance issues
- Refactoring existing React/Next.js code
- Optimizing bundle size or load times
Rule Categories by Priority
| Priority | Category | Impact | Prefix |
|---|---|---|---|
| 1 | Eliminating Waterfalls | CRITICAL | async- |
| 2 | Bundle Size Optimization | CRITICAL | bundle- |
| 3 | Server-Side Performance | HIGH | server- |
| 4 | Client-Side Data Fetching | MEDIUM-HIGH | client- |
| 5 | Re-render Optimization | MEDIUM | rerender- |
| 6 | Rendering Performance | MEDIUM | rendering- |
| 7 | JavaScript Performance | LOW-MEDIUM | js- |
| 8 | Advanced Patterns | LOW | advanced- |
Quick Reference
1. Eliminating Waterfalls (CRITICAL)
async-defer-await— MUST move await into branches where actually usedasync-parallel— MUST use Promise.all() for independent operationsasync-dependencies— SHOULD use better-all for partial dependenciesasync-api-routes— MUST start promises early, await late in API routesasync-suspense-boundaries— SHOULD use Suspense to stream content
2. Bundle Size Optimization (CRITICAL)
bundle-barrel-imports— MUST import directly, avoid barrel filesbundle-dynamic-imports— SHOULD use next/dynamic for heavy componentsbundle-defer-third-party— SHOULD load analytics/logging after hydrationbundle-conditional— SHOULD load modules only when feature is activatedbundle-preload— MAY preload on hover/focus for perceived speed
3. Server-Side Performance (HIGH)
server-auth-actions— MUST authenticate server actions like API routesserver-cache-react— SHOULD use React.cache() for per-request deduplicationserver-cache-lru— MAY use LRU cache for cross-request cachingserver-dedup-props— SHOULD avoid duplicate serialization in RSC propsserver-hoist-static-io— SHOULD hoist static I/O (fonts, logos) to module levelserver-serialization— SHOULD minimize data passed to client componentsserver-parallel-fetching— SHOULD restructure components to parallelize fetchesserver-after-nonblocking— MAY use after() for non-blocking operations
4. Client-Side Data Fetching (MEDIUM-HIGH)
client-swr-dedup— SHOULD use SWR for automatic request deduplicationclient-event-listeners— SHOULD deduplicate global event listenersclient-passive-event-listeners— SHOULD use passive listeners for scrollclient-localstorage-schema— SHOULD version and minimize localStorage data
5. Re-render Optimization (MEDIUM)
rerender-defer-reads— SHOULD NOT subscribe to state only used in callbacksrerender-memo— SHOULD extract expensive work into memoized componentsrerender-memo-with-default-value— SHOULD hoist default non-primitive propsrerender-dependencies— SHOULD use primitive dependencies in effectsrerender-derived-state— SHOULD subscribe to derived booleans, not raw valuesrerender-derived-state-no-effect— MUST derive state during render, not effectsrerender-functional-setstate— SHOULD use functional setState for stable callbacksrerender-lazy-state-init— SHOULD pass function to useState for expensive valuesrerender-simple-expression-in-memo— SHOULD NOT use memo for simple primitivesrerender-move-effect-to-event— SHOULD put interaction logic in event handlersrerender-transitions— MAY use startTransition for non-urgent updatesrerender-use-ref-transient-values— SHOULD use refs for transient frequent values
6. Rendering Performance (MEDIUM)
rendering-animate-svg-wrapper— SHOULD animate div wrapper, not SVG elementrendering-content-visibility— MAY use content-visibility for long listsrendering-hoist-jsx— SHOULD extract static JSX outside componentsrendering-svg-precision— SHOULD reduce SVG coordinate precisionrendering-hydration-no-flicker— SHOULD use inline script for client-only datarendering-hydration-suppress-warning— MAY suppress expected mismatchesrendering-activity— MAY use Activity component for show/hiderendering-conditional-render— MUST use ternary, not && for conditionalsrendering-usetransition-loading— SHOULD prefer useTransition for loading state
7. JavaScript Performance (LOW-MEDIUM)
js-batch-dom-css— SHOULD group CSS changes via classes or cssTextjs-index-maps— SHOULD build Map for repeated lookupsjs-cache-property-access— SHOULD cache object properties in loopsjs-cache-function-results— MAY cache function results in module-level Mapjs-cache-storage— SHOULD cache localStorage/sessionStorage readsjs-combine-iterations— SHOULD combine multiple filter/map into one loopjs-length-check-first— SHOULD check array length before expensive comparisonjs-early-exit— SHOULD return early from functionsjs-hoist-regexp— SHOULD hoist RegExp creation outside loopsjs-min-max-loop— MAY use loop for min/max instead of sortjs-set-map-lookups— SHOULD use Set/Map for O(1) lookupsjs-tosorted-immutable— SHOULD use toSorted() for immutability
8. Advanced Patterns (LOW)
advanced-event-handler-refs— MAY store event handlers in refsadvanced-init-once— SHOULD initialize app once per app loadadvanced-use-latest— MAY use useLatest for stable callback refs
How to Use
Read individual rule files for detailed explanations and code examples:
rules/async-parallel.md
rules/bundle-barrel-imports.md
Each rule file contains:
- Brief explanation of why it matters
- Incorrect code example with explanation
- Correct code example with explanation
- Additional context and references
Full Compiled Document
For the complete guide with all rules expanded: AGENTS.md