From qe-framework
Performance optimization guidelines for React and Next.js applications from Vercel Engineering. Apply when writing, reviewing, or refactoring components, pages, data fetching, and bundle optimization.
How this skill is triggered — by the user, by Claude, or both
Slash command
/qe-framework:Qreact-best-practicesThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Comprehensive performance optimization guide for React and Next.js applications, maintained by Vercel. Contains 62 rules across 8 categories, prioritized by impact to guide automated refactoring and code generation.
README.mdmetadata.jsonreferences/react-patterns.mdrules/_sections.mdrules/_template.mdrules/advanced-event-handler-refs.mdrules/advanced-init-once.mdrules/advanced-use-latest.mdrules/async-api-routes.mdrules/async-defer-await.mdrules/async-dependencies.mdrules/async-parallel.mdrules/async-suspense-boundaries.mdrules/bundle-barrel-imports.mdrules/bundle-conditional.mdrules/bundle-defer-third-party.mdrules/bundle-dynamic-imports.mdrules/bundle-preload.mdrules/client-event-listeners.mdrules/client-localstorage-schema.mdComprehensive performance optimization guide for React and Next.js applications, maintained by Vercel. Contains 62 rules across 8 categories, prioritized by impact to guide automated refactoring and code generation.
Reference these guidelines when:
| 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- |
async-defer-await - Move await into branches where actually usedasync-parallel - Use Promise.all() for independent operationsasync-dependencies - Use better-all for partial dependenciesasync-api-routes - Start promises early, await late in API routesasync-suspense-boundaries - Use Suspense to stream contentbundle-barrel-imports - Import directly, avoid barrel filesbundle-dynamic-imports - Use next/dynamic for heavy componentsbundle-defer-third-party - Load analytics/logging after hydrationbundle-conditional - Load modules only when feature is activatedbundle-preload - Preload on hover/focus for perceived speedserver-auth-actions - Authenticate server actions like API routesserver-cache-react - Use React.cache() for per-request deduplicationserver-cache-lru - Use LRU cache for cross-request cachingserver-dedup-props - Avoid duplicate serialization in RSC propsserver-hoist-static-io - Hoist static I/O (fonts, logos) to module levelserver-serialization - Minimize data passed to client componentsserver-parallel-fetching - Restructure components to parallelize fetchesserver-after-nonblocking - Use after() for non-blocking operationsclient-swr-dedup - Use SWR for automatic request deduplicationclient-event-listeners - Deduplicate global event listenersclient-passive-event-listeners - Use passive listeners for scrollclient-localstorage-schema - Version and minimize localStorage datarerender-defer-reads - Don't subscribe to state only used in callbacksrerender-memo - Extract expensive work into memoized componentsrerender-memo-with-default-value - Hoist default non-primitive propsrerender-dependencies - Use primitive dependencies in effectsrerender-derived-state - Subscribe to derived booleans, not raw valuesrerender-derived-state-no-effect - Derive state during render, not effectsrerender-functional-setstate - Use functional setState for stable callbacksrerender-lazy-state-init - Pass function to useState for expensive valuesrerender-simple-expression-in-memo - Avoid memo for simple primitivesrerender-move-effect-to-event - Put interaction logic in event handlersrerender-transitions - Use startTransition for non-urgent updatesrerender-use-ref-transient-values - Use refs for transient frequent valuesrerender-no-inline-components - Don't define components inside componentsrendering-animate-svg-wrapper - Animate div wrapper, not SVG elementrendering-content-visibility - Use content-visibility for long listsrendering-hoist-jsx - Extract static JSX outside componentsrendering-svg-precision - Reduce SVG coordinate precisionrendering-hydration-no-flicker - Use inline script for client-only datarendering-hydration-suppress-warning - Suppress expected mismatchesrendering-activity - Use Activity component for show/hiderendering-conditional-render - Use ternary, not && for conditionalsrendering-usetransition-loading - Prefer useTransition for loading staterendering-resource-hints - Use React DOM resource hints for preloadingrendering-script-defer-async - Use defer or async on script tagsjs-batch-dom-css - Group CSS changes via classes or cssTextjs-index-maps - Build Map for repeated lookupsjs-cache-property-access - Cache object properties in loopsjs-cache-function-results - Cache function results in module-level Mapjs-cache-storage - Cache localStorage/sessionStorage readsjs-combine-iterations - Combine multiple filter/map into one loopjs-length-check-first - Check array length before expensive comparisonjs-early-exit - Return early from functionsjs-hoist-regexp - Hoist RegExp creation outside loopsjs-min-max-loop - Use loop for min/max instead of sortjs-set-map-lookups - Use Set/Map for O(1) lookupsjs-tosorted-immutable - Use toSorted() for immutabilityjs-flatmap-filter - Use flatMap to map and filter in one passadvanced-event-handler-refs - Store event handlers in refsadvanced-init-once - Initialize app once per app loadadvanced-use-latest - useLatest for stable callback refsEssential React optimization patterns (3 levels):
Basic: Memo + useMemo — Cache expensive computations
const Avatar = memo(({ user }) => {
const id = useMemo(() => computeAvatarId(user), [user])
return <Avatar id={id} />
})
Error Handling: Suspense + ErrorBoundary — Resilient async rendering
<ErrorBoundary fallback={<ErrorUI />}>
<Suspense fallback={<Skeleton />}>
<AsyncData />
</Suspense>
</ErrorBoundary>
Advanced: useTransition — Non-blocking updates
const handler = () => startTransition(() => setScrollY(window.scrollY))
JSDoc for React components: @param, @returns, @since (internal). Example:
/**
* Paginated user list with lazy rendering.
* @param {User[]} users
* @returns {ReactNode} List with controls
*/
ESLint: plugin:react/recommended, plugin:react-hooks/recommended
Key rules: react-hooks/rules-of-hooks (error), exhaustive-deps (warn), jsx-no-target-blank (error)
TypeScript: tsc --noEmit before commit
dangerouslySetInnerHTML; sanitize with DOMPurifynpm audit monthly, enable dependabotReference rules/ for full details. These 5 pairs highlight common mistakes:
| Wrong | Correct | Rule |
|---|---|---|
if (loading && <Component />) | {loading ? <Skeleton /> : <Component />} | rendering-conditional-render |
const Avatar = () => { ... } inside component | Extract to module scope | rerender-no-inline-components |
setState(old => old + 1) in effect loop | Use functional setState in callbacks | rerender-functional-setstate |
await data; return jsx; blocking entire page | Use Suspense boundaries per section | async-suspense-boundaries |
import { a, b, c } from './utils' barrel | import { a } from './utils/a' | bundle-barrel-imports |
Read individual rule files for detailed explanations and code examples:
rules/async-parallel.md
rules/bundle-barrel-imports.md
rules/rerender-memo.md
rules/async-suspense-boundaries.md
rules/rerender-transitions.md
Each rule file contains:
Reference: see references/react-patterns.md for detailed patterns.
For the complete guide with all rules expanded: references/react-patterns.md
npx claudepluginhub inho-team/qe-framework --plugin qe-frameworkCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.