AgentSkillsCN

react-performance

Vercel 工程团队提供的 React 与 Next.js 性能优化方案。涵盖 8 大类共 45 条规则,涉及异步瀑布、包体积、服务器端性能、重新渲染,以及渲染优化。适用于编写、审查或优化 React/Next.js 代码的场景。

SKILL.md
--- frontmatter
name: react-performance
description: React and Next.js performance optimization from Vercel Engineering. 45 rules across 8 categories covering async waterfalls, bundle size, server-side performance, re-renders, and rendering optimization. Use when writing, reviewing, or optimizing React/Next.js code.

React Performance Optimization

Philosophy: Performance is a feature. Every millisecond matters for user experience and conversion. Prevent performance regressions through systematic rule application, not reactive optimization.


Rule Categories by Priority

PriorityCategoryPrefixRulesImpact
CRITICALEliminating Waterfallsasync-5Blocks rendering, causes cascading delays
CRITICALBundle Size Optimizationbundle-5Affects initial load, TTI, LCP
HIGHServer-Side Performanceserver-5RSC efficiency, caching, streaming
HIGHRe-render Optimizationrerender-8UI responsiveness, CPU usage
MEDIUMRendering Performancerender-7Paint performance, layout thrashing
MEDIUMJavaScript Performancejs-12Runtime efficiency, memory
LOWNetwork Optimizationnetwork-2Request efficiency
LOWMemory Managementmemory-1Memory leaks, GC pressure

Quick Reference

Eliminating Waterfalls (async-)

RuleDescription
async-parallelUse Promise.all for independent operations
async-preloadPreload data before navigation
async-streamingStream responses with Suspense boundaries
async-prefetchPrefetch likely next pages
async-deferredDefer non-critical data fetching

Bundle Size Optimization (bundle-)

RuleDescription
bundle-barrel-importsUse direct imports, avoid barrel files
bundle-dynamic-importsLazy load with next/dynamic
bundle-tree-shakingEnsure proper tree-shaking
bundle-external-depsAnalyze and minimize dependencies
bundle-code-splittingSplit by route and feature

Server-Side Performance (server-)

RuleDescription
server-cache-reactUse React.cache for request deduplication
server-cache-nextUse unstable_cache for cross-request caching
server-streamingStream long-running operations
server-edgeUse Edge Runtime when possible
server-pprEnable Partial Prerendering

Re-render Optimization (rerender-)

RuleDescription
rerender-memoExtract expensive computations
rerender-callbackStabilize callback references
rerender-contextSplit contexts by update frequency
rerender-state-colocationKeep state close to usage
rerender-derivedDerive state instead of syncing
rerender-refUse refs for values that don't need renders
rerender-childrenUse children prop for composition
rerender-keyUse stable, meaningful keys

Rendering Performance (render-)

RuleDescription
render-virtualizeVirtualize long lists
render-css-containmentUse CSS containment
render-layout-thrashingBatch DOM reads and writes
render-transformPrefer transform over layout properties
render-will-changeUse will-change sparingly
render-layersManage compositor layers
render-paintMinimize paint areas

JavaScript Performance (js-)

RuleDescription
js-debounceDebounce frequent events
js-throttleThrottle continuous events
js-web-workerOffload heavy computation
js-idle-callbackSchedule non-urgent work
js-intersectionUse IntersectionObserver
js-resizeUse ResizeObserver
js-passiveUse passive event listeners
js-delegationUse event delegation
js-loopOptimize loop operations
js-object-poolingReuse objects in hot paths
js-string-concatUse template literals
js-array-methodsChoose optimal array methods

Critical Rule Patterns

async-parallel: Promise.all for Independent Operations

typescript
// BAD: Sequential waterfall
async function loadDashboard() {
  const user = await fetchUser()
  const posts = await fetchPosts()
  const notifications = await fetchNotifications()
  return { user, posts, notifications }
}

// GOOD: Parallel execution
async function loadDashboard() {
  const [user, posts, notifications] = await Promise.all([
    fetchUser(),
    fetchPosts(),
    fetchNotifications(),
  ])
  return { user, posts, notifications }
}

bundle-barrel-imports: Direct Imports

typescript
// BAD: Barrel import pulls entire module
import { Button } from '@/components'
import { formatDate } from '@/utils'

// GOOD: Direct imports enable tree-shaking
import { Button } from '@/components/ui/button'
import { formatDate } from '@/utils/date'

bundle-dynamic-imports: next/dynamic

typescript
// BAD: Static import of heavy component
import { CodeEditor } from '@/components/code-editor'

// GOOD: Dynamic import with loading state
import dynamic from 'next/dynamic'

const CodeEditor = dynamic(
  () => import('@/components/code-editor'),
  {
    loading: () => <EditorSkeleton />,
    ssr: false, // Client-only component
  }
)

server-cache-react: React.cache for Deduplication

typescript
import { cache } from 'react'

// Deduplicated across component tree in single request
export const getUser = cache(async (id: string) => {
  const response = await fetch(`/api/users/${id}`)
  return response.json()
})

// Multiple components can call getUser(id) - only one fetch

rerender-memo: Extract Expensive Work

typescript
// BAD: Recalculates on every render
function Dashboard({ items }) {
  const sorted = items.sort((a, b) => b.priority - a.priority)
  const filtered = sorted.filter(item => item.active)
  const total = filtered.reduce((sum, item) => sum + item.value, 0)
  
  return <DashboardView items={filtered} total={total} />
}

// GOOD: Memoized expensive computation
function Dashboard({ items }) {
  const { filtered, total } = useMemo(() => {
    const sorted = [...items].sort((a, b) => b.priority - a.priority)
    const filtered = sorted.filter(item => item.active)
    const total = filtered.reduce((sum, item) => sum + item.value, 0)
    return { filtered, total }
  }, [items])
  
  return <DashboardView items={filtered} total={total} />
}

Adherence Checklist

Before completing your task, verify:

  • Waterfalls: Are independent async operations parallelized?
  • Imports: Are imports direct (not barrel) for tree-shaking?
  • Dynamic: Are heavy/optional components dynamically imported?
  • Caching: Is React.cache used for request deduplication?
  • Memoization: Are expensive computations memoized?
  • State: Is state colocated near its usage?
  • Lists: Are long lists virtualized?
  • Events: Are frequent events debounced/throttled?

Extended Reference

See references/rules.md for complete rule explanations with code examples for all 45 rules.