Vercel React 最佳实践
由 Vercel 维护的 React 和 Next.js 应用性能优化综合指南。包含 8 个类别共 70 条规则,按影响程度排序,旨在指导自动化重构和代码生成。
安装
npx skills add https://github.com/vercel-labs/agent-skills --skill vercel-react-best-practices
概述
React 和 Next.js 性能优化指南,包含 8 个类别共 64 条优先级规则。
- 按影响级别组织,从关键的瀑布式优化和捆绑包优化到高级模式;每条规则都包含错误/正确的代码示例和解释。
- 涵盖八个领域:异步模式、包大小、服务器端缓存、客户端数据获取、重新渲染优化、渲染性能、JavaScript 效率和高级模式。
- 专为 React 和 Next.js 应用程序的组件编写、代码审查、重构和性能审计而设计。
- 每条规则都有一个前缀代码(例如
async-parallel、bundle-barrel-imports),以便在自动化工具和文档中轻松引用。
何时申请
在以下情况下请参考这些准则:
- 编写新的 React 组件或 Next.js 页面
- 实现数据获取(客户端或服务器端)
- 审查代码是否存在性能问题
- 重构现有的 React/Next.js 代码
- 优化捆绑包大小或加载时间
按优先级划分的规则类别
| 优先级 | 类别 | 影响 | 前缀 |
|---|---|---|---|
| 1 | 消除瀑布 | 关键 | async- |
| 2 | 捆绑包大小优化 | 关键 | bundle- |
| 3 | 服务器端性能 | 高 | server- |
| 4 | 客户端数据获取 | 中高 | client- |
| 5 | 重新渲染优化 | 中等 | rerender- |
| 6 | 渲染性能 | 中等 | rendering- |
| 7 | JavaScript 性能 | 低–中 | js- |
| 8 | 高级模式 | 低 | advanced- |
快速参考
1. 消除瀑布式流程(至关重要)
| 规则 ID | 说明 |
|---|---|
async-cheap-condition-before-await | 在等待标志或远程值之前,检查低成本同步条件 |
async-defer-await | 将 await 移到实际使用的分支中 |
async-parallel | 使用 Promise.all() 进行独立操作 |
async-dependencies | 对于部分依赖项,请使用 better-all |
async-api-routes | 在 API 路由中,尽早启动 Promise,延迟 await |
async-suspense-boundaries | 使用 Suspense 来流式展示内容 |
2. 包大小优化(至关重要)
| 规则 ID | 说明 |
|---|---|
bundle-barrel-imports | 直接导入,避免使用 barrel 文件 |
bundle-analyzable-paths | 优先选择可静态分析的导入路径和文件系统路径 |
bundle-dynamic-imports | 对于大型组件,请使用 next/dynamic |
bundle-defer-third-party | 水合后加载分析/日志 |
bundle-conditional | 仅在功能激活时加载模块 |
bundle-preload | 悬停/聚焦时预加载,以提升感知速度 |
3. 服务器端性能(高)
| 规则 ID | 说明 |
|---|---|
server-auth-actions | 对 Server Actions(例如 API 路由)进行身份验证 |
server-cache-react | 使用 React.cache() 进行每次请求的去重 |
server-cache-lru | 使用 LRU 缓存进行跨请求缓存 |
server-dedup-props | 避免 RSC props 中重复序列化 |
server-hoist-static-io | 将静态 I/O(字体、徽标)提升到模块级 |
server-no-shared-module-state | 避免在 RSC/SSR 中使用模块级可变请求状态 |
server-serialization | 最大程度减少传递给客户端组件的数据量 |
server-parallel-fetching | 重构组件以实现并行获取 |
server-parallel-nested-fetching | 在 Promise.all 中对每个项目进行链式嵌套获取 |
server-after-nonblocking | 对于非阻塞操作,请使用 after() |
4. 客户端数据获取(中高)
| 规则 ID | 说明 |
|---|---|
client-swr-dedup | 使用 SWR 进行自动请求去重 |
client-event-listeners | 删除重复的全局事件监听器 |
client-passive-event-listeners | 使用 passive 监听器监听滚动事件 |
client-localstorage-schema | 版本控制并最小化 localStorage 数据 |
5. 重新渲染优化(中)
| 规则 ID | 说明 |
|---|---|
rerender-defer-reads | 不要订阅仅在回调中使用的状态 |
rerender-memo | 将耗时的工作提取到记忆化组件中 |
rerender-memo-with-default-value | 提升默认的非原始 props |
rerender-dependencies | 在副作用中使用原始依赖项 |
rerender-derived-state | 订阅派生布尔值,而不是原始值 |
rerender-derived-state-no-effect | 在渲染期间派生状态,而不是 effect |
rerender-functional-setstate | 使用函数式 setState 实现稳定的回调 |
rerender-lazy-state-init | 将函数传递给 useState 以处理昂贵的初始值 |
rerender-simple-expression-in-memo | 对于简单的基本元素,避免使用 memo |
rerender-split-combined-hooks | 拆分具有独立依赖项的 hooks |
rerender-move-effect-to-event | 将交互逻辑放在事件处理程序中 |
rerender-transitions | 对于非紧急更新,请使用 startTransition |
rerender-use-deferred-value | 使用 useDeferredValue 保持输入响应迅速 |
rerender-use-ref-transient-values | 使用 ref 表示瞬态频繁值 |
rerender-no-inline-components | 不要在组件内部定义组件 |
6. 渲染性能(中等)
| 规则 ID | 说明 |
|---|---|
rendering-animate-svg-wrapper | 为 div 容器添加动画,而不是 SVG 元素 |
rendering-content-visibility | 对长列表使用 content-visibility |
rendering-hoist-jsx | 从组件外部提取静态 JSX |
rendering-svg-precision | 降低 SVG 坐标精度 |
rendering-hydration-no-flicker | 使用内联脚本处理仅供客户端使用的数据 |
rendering-hydration-suppress-warning | 抑制预期中的 hydration 不匹配警告 |
rendering-activity | 使用 Activity 组件进行显示/隐藏 |
rendering-conditional-render | 条件渲染请使用三元运算符,而不是 && |
rendering-usetransition-loading | 使用 Transition 表示加载状态 |
rendering-resource-hints | 使用 React DOM 资源提示进行预加载 |
rendering-script-defer-async | 在 script 标签中使用 defer 或 async |
7. JavaScript 性能(低–中等)
| 规则 ID | 说明 |
|---|---|
js-batch-dom-css | 通过 class 或 cssText 对 CSS 更改进行分组 |
js-index-maps | 构建 Map 用于重复查找 |
js-cache-property-access | 在循环中缓存对象属性 |
js-cache-function-results | 在模块级 Map 中缓存函数结果 |
js-cache-storage | 缓存 localStorage / sessionStorage 读取 |
js-combine-iterations | 将多个 filter / map 合并到一个循环中 |
js-length-check-first | 在进行昂贵的比较之前检查数组长度 |
js-early-exit | 提前结束函数 |
js-hoist-regexp | 在循环外创建提升的正则表达式 |
js-min-max-loop | 使用循环查找最小/最大值,而不是排序 |
js-set-map-lookups | 使用 Set/Map 进行 O(1) 查找 |
js-tosorted-immutable | 使用 toSorted() 实现不可变性 |
js-flatmap-filter | 使用 flatMap 一次性完成映射和过滤 |
js-request-idle-callback | 将非关键工作推迟到 requestIdleCallback |
8. 高级模式(低)
| 规则 ID | 说明 |
|---|---|
advanced-effect-event-deps | 不要将 useEffectEvent 结果纳入 effect 依赖 |
advanced-event-handler-refs | 将事件处理程序存储在 ref 中 |
advanced-init-once | 每次应用加载时初始化一次 |
advanced-use-latest | 使用 useLatest 作为稳定的回调引用 |
如何使用
请阅读各个规则文件以获取详细说明和代码示例:
rules/async-parallel.mdrules/bundle-barrel-imports.md
每个规则文件包含:
- 简要解释其重要性
- 错误代码示例及解释
- 正确的代码示例及解释
- 更多背景信息和参考资料
完整汇编文件
完整规则详解请见:AGENTS.md