React Best Practices

Vercel 工程团队提供的 React 与 Next.js 性能优化规则,涵盖 8 类共 57 条最佳实践。

已扫描
适合谁
前端开发工程师、React/Next.js 项目负责人
不适合谁
无 React 经验的初学者、仅需简单页面展示的非技术用户
国内可用性
需网络配置。可能需要网络配置或第三方服务可访问。
安装难度
新手友好(★☆☆)。基于终端操作、依赖、API Key 和本地环境要求的初步判断。

安装与下载

openclaw skills install @wpank/react-best-practices

Skill 说明

命令、参数、文件名以原文为准

React 最佳实践

Vercel 工程团队提供的 React 与 Next.js 应用性能优化完整指南。包含 8 个类别共 57 条规则,按影响程度优先级排序。

安装

OpenClaw / Moltbot / Clawbot

npx clawhub@latest install react-best-practices

本技能的作用

提供可操作的规则,帮助实现:

  • 消除请求瀑布流
  • 优化打包体积
  • 提升服务端性能
  • 高效的客户端数据获取
  • 减少不必要的重新渲染
  • 渲染性能优化
  • JavaScript 微优化
  • 复杂场景下的高级模式

适用场景

  • 编写新的 React 组件或 Next.js 页面时
  • 实现数据获取(客户端或服务端)
  • 审查代码中的性能问题
  • 重构 React/Next.js 应用
  • 优化打包体积或加载时间
  • 调试渲染缓慢或请求瀑布问题

关键词

react 性能, nextjs 优化, 打包体积, 水瀑布, suspense, 服务端组件, rsc, 重新渲染, usememo, 动态导入, 并行获取, 缓存, swr

规则类别优先级

优先级类别影响程度规则前缀
1消除瀑布流至关重要async-
2打包体积优化至关重要bundle-
3服务端性能server-
4客户端数据获取中高client-
5重新渲染优化rerender-
6渲染性能rendering-
7JavaScript 性能低中js-
8高级模式advanced-

快速参考

1. 消除瀑布流(至关重要)

规则说明
async-defer-awaitawait 放入实际使用的位置分支中
async-parallel对独立操作使用 Promise.all()
async-dependencies使用 better-all 处理部分依赖
async-api-routes在 API 路由中尽早启动 Promise,延迟 await
async-suspense-boundaries使用 Suspense 流式传输内容

2. 打包体积优化(至关重要)

规则说明
bundle-barrel-imports直接导入,避免使用 barrel 文件
bundle-dynamic-imports对重型组件使用 next/dynamic
bundle-defer-third-party在页面首次渲染后才加载分析、日志等第三方脚本
bundle-conditional仅在功能启用时才加载对应模块
bundle-preload在悬停或聚焦时预加载,提升感知速度

3. 服务端性能(高)

规则说明
server-auth-actions像处理 API 路由一样对服务端动作进行身份验证
server-cache-react使用 React.cache() 实现每请求去重
server-cache-lru使用 LRU 缓存实现跨请求缓存
server-dedup-props避免在 RSC props 中重复序列化数据
server-serialization减少传递给客户端组件的数据量
server-parallel-fetching重构组件以并行发起数据请求
server-after-nonblocking对非阻塞操作使用 after()

4. 客户端数据获取(中高)

规则说明
client-swr-dedup使用 SWR 实现自动请求去重
client-event-listeners避免全局事件监听器重复注册
client-passive-event-listeners滚动事件使用被动监听器
client-localstorage-schema对 localStorage 数据进行版本控制并最小化存储

5. 重新渲染优化(中)

规则说明
rerender-defer-reads不要订阅仅在回调中使用的状态
rerender-memo将耗时计算提取到 memoized 组件中
rerender-memo-with-default-value将非原始类型的默认 props 提前声明
rerender-dependencies在 effects 中使用原始类型依赖项
rerender-derived-state订阅派生布尔值,而非原始值
rerender-derived-state-no-effect在渲染阶段推导状态,而非通过 effect
rerender-functional-setstate使用函数式 setState 保持回调稳定
rerender-lazy-state-inituseState 传入函数以延迟初始化昂贵值
rerender-simple-expression-in-memo简单原始值无需使用 memo
rerender-move-effect-to-event将交互逻辑移至事件处理器中
rerender-transitions对非紧急更新使用 startTransition
rerender-use-ref-transient-values对频繁变化的临时值使用 ref

6. 渲染性能(中)

规则说明
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抑制预期的渲染不一致警告
rendering-activity使用 Activity 组件管理显示/隐藏逻辑
rendering-conditional-render使用三元表达式,而非 && 进行条件渲染
rendering-usetransition-loading优先使用 useTransition 管理加载状态

7. JavaScript 性能(低-中)

技能:React 最佳实践

版本:1.0.0

分块:2/2

规则说明
js-batch-dom-css通过类名或 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() 保证不可变性

8. 高级模式(低优先级)

规则说明
advanced-event-handler-refs将事件处理器存储在 refs 中
advanced-init-once每次应用加载时仅初始化一次
advanced-use-latest使用 useLatest 保持回调引用的稳定性

如何使用

阅读单个规则

每个 rules/ 目录下的规则文件包含:

  • 简要说明为何重要
  • 错误代码示例及解释
  • 正确代码示例及解释
  • 补充上下文与参考资料
rules/async-parallel.md
rules/bundle-barrel-imports.md
rules/rerender-memo.md

完整编译文档

获取包含所有规则的完整指南:AGENTS.md

此超过 2900 行的文档包含了每条规则的完整代码示例和详细说明,适合作为全面参考。

核心模式

并行数据获取

// 低效:顺序执行
const user = await fetchUser()
const posts = await fetchPosts()

// 优化:并行执行
const [user, posts] = await Promise.all([
  fetchUser(),
  fetchPosts()
])

动态导入

// 低效:将 Monaco 打包进主 chunk
import { MonacoEditor } from './monaco-editor'

// 优化:按需加载
const MonacoEditor = dynamic(
  () => import('./monaco-editor').then(m => m.MonacoEditor),
  { ssr: false }
)

函数式 setState

// 低效:存在闭包过期风险
const addItem = useCallback((item) => {
  setItems([...items, item])
}, [items]) // 每次 items 变化都会重新创建

// 优化:始终使用最新状态
const addItem = useCallback((item) => {
  setItems(curr => [...curr, item])
}, []) // 引用稳定

绝对不要这样做

  1. 绝不要 串行等待本可并行执行的操作
  2. 绝不要 从 barrel 文件导入(如 import { X } from 'lib')——应直接导入具体模块
  3. 绝不要 在 Server Actions 中跳过认证——应视同 API 路由处理
  4. 绝不要 将整个对象传递给客户端组件,若仅需其中一字段
  5. 绝不要 使用 && 进行数值的条件渲染——应使用三元表达式
  6. 绝不要 仅在事件处理器中订阅状态——应按需读取
  7. 绝不要 使用 .sort() 修改数组——应使用 .toSorted()
  8. 绝不要 将初始化逻辑放在 useEffect([]) 中——应在模块级别使用保护机制
W
@wpank

已收录 11 个 Skill

相关推荐