文章目录
- 前言
- Guidelines
- Rendering Patterns
- Animate SVG wrappers, not SVG elements directly
- 核心问题
- 反例:直接动画
- 推荐:动画容器
- 典型场景
- Use content-visibility: auto for long lists
- 核心问题
- 反例:普通列表
- 推荐:content-visibility
- 额外技巧
- Prevent hydration mismatch with inline scripts
- 核心问题
- 反例:SSR 内直接修改 DOM
- 推荐做法
- 场景
- Use explicit conditional rendering
- 核心问题
- 反例:用 &&
- 推荐:用三元
- 额外注意
- 总结
前言
react-best-practices
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.
Guidelines
在这个系列,我会逐条拆解,每一条都给出:
- 核心问题是什么
- 为什么会慢(本质原因)
- 典型业务场景
- 反例代码
- 推荐写法
- 在 React / Next.js 中的实际收益
Rendering Patterns
这是系列的第四部分。
Animate SVG wrappers, not SVG elements directly
「不要直接在 SVG 元素上做动画」
核心问题
- SVG 元素本身(
<path>、<circle>)渲染成本高 - 动画会频繁触发 repaint / reflow
- 会严重影响性能,尤其在大量节点或复杂图形中
反例:直接动画
<svg width="100"height="100"><circle cx="50"cy="50"r="40"fill="red"style={{transform:`rotate(${angle}deg)`}}/></svg>每次angle更新,浏览器必须重绘整个<circle>
推荐:动画容器
<div style={{transform:`rotate(${angle}deg)`}}><svg width="100"height="100"><circle cx="50"cy="50"r="40"fill="red"/></svg></div>好处:
- 浏览器只在
<div>上做 GPU transform <svg>内容不会被重复绘制- 动画性能大幅提升
典型场景
- 仪表盘指针
- loading spinner
- 图表动态旋转
Use content-visibility: auto for long lists
「长列表使用 content-visibility 延迟渲染」
核心问题
- 浏览器渲染大 DOM(数百 / 千行)性能低
- 每次 scroll / paint 都计算 layout
反例:普通列表
<ul>{data.map(item=><li key={item.id}>{item.name}</li>)}</ul>- 1000 行 → 每次渲染 / scroll 都会 layout / paint
推荐:content-visibility
<ul style={{contentVisibility:'auto',containIntrinsicSize:'1000px'}}>{data.map(item=><li key={item.id}>{item.name}</li>)}</ul>好处:
- 浏览器只渲染可视区域
- DOM 节点仍在 document flow
- 性能接近虚拟列表,但不依赖 JS
额外技巧
contain-intrinsic-size提前占位- 对表格、卡片、长文列表非常适用
Prevent hydration mismatch with inline scripts
「避免 hydration mismatch / 客户端渲染与服务端不一致」
核心问题
- React SSR + RSC / Next.js
- 服务端生成 HTML → 客户端 hydrate
- 如果 inline JS 改变 DOM 或插入元素
- 会导致Hydration Mismatch→ 控制台报错 / UI 闪烁
反例:SSR 内直接修改 DOM
<div dangerouslySetInnerHTML={{__html:`<script>document.body.style.background='red'</script>`}}/>- 服务端生成的 DOM 和客户端 React DOM不一致
- React hydrate 失败
推荐做法
- 用useEffect / useLayoutEffect在客户端处理
useEffect(() => { document.body.style.background = 'red' }, [])SSR 阶段不改 DOM → 避免 mismatch
场景
- 动态插入广告 / 脚本
- 第三方库初始化
- UI 初始化特效
Use explicit conditional rendering
「条件渲染用三元表达式,而不是 &&」
核心问题
false && <Component />会渲染false→ 有时造成空 DOM / Hydration mismatch- 特别在 SSR / Client Hydration 时容易出错
反例:用 &&
{isVisible && <Modal />}- SSR:
isVisible=false→ 渲染false - Client:
isVisible=true→ 渲染<Modal /> - React 可能报 hydration mismatch
推荐:用三元
{isVisible ? <Modal /> : null}- SSR / Client 渲染保持一致
- Hydration 安全
额外注意
- 对列表也适用:
{/* ❌ 不推荐 */} {items.length && <List items={items} />} {/* ✅ 推荐 */} {items.length > 0 ? <List items={items} /> : null}总结
Rendering Patterns =让浏览器和 React 都高效
- SVG 动画 → wrapper transform
- 长列表 → content-visibility
- SSR → hydrate 安全
- 条件渲染 → 明确三元