文章目录
- 前言
- Guidelines
- [Rendering Patterns](#Rendering Patterns)
-
- [Animate SVG wrappers, not SVG elements directly](#Animate SVG wrappers, not SVG elements directly)
- [Use content-visibility: auto for long lists](#Use content-visibility: auto for long lists)
- [Prevent hydration mismatch with inline scripts](#Prevent hydration mismatch with inline scripts)
- [Use explicit conditional rendering](#Use explicit conditional rendering)
- 总结
前言
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
- 会严重影响性能,尤其在大量节点或复杂图形中
反例:直接动画
ts
<svg width="100" height="100">
<circle
cx="50"
cy="50"
r="40"
fill="red"
style={{ transform: `rotate(${angle}deg)` }}
/>
</svg>
每次 angle 更新,浏览器必须重绘整个 <circle>
推荐:动画容器
ts
<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
反例:普通列表
ts
<ul>
{data.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
- 1000 行 → 每次渲染 / scroll 都会 layout / paint
推荐:content-visibility
ts
<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
ts
<div dangerouslySetInnerHTML={{ __html: `<script>document.body.style.background='red'</script>` }} />
- 服务端生成的 DOM 和客户端 React DOM 不一致
- React hydrate 失败
推荐做法
- 用 useEffect / useLayoutEffect 在客户端处理
tsx
useEffect(() => {
document.body.style.background = 'red'
}, [])
SSR 阶段不改 DOM → 避免 mismatch
场景
- 动态插入广告 / 脚本
- 第三方库初始化
- UI 初始化特效
Use explicit conditional rendering
「条件渲染用三元表达式,而不是 &&」
核心问题
false && <Component />会渲染 false → 有时造成空 DOM / Hydration mismatch- 特别在 SSR / Client Hydration 时容易出错
反例:用 &&
tsx
{isVisible && <Modal />}
- SSR:
isVisible=false→ 渲染false - Client:
isVisible=true→ 渲染<Modal /> - React 可能报 hydration mismatch
推荐:用三元
tsx
{isVisible ? <Modal /> : null}
- SSR / Client 渲染保持一致
- Hydration 安全
额外注意
- 对列表也适用:
tsx
{/* ❌ 不推荐 */}
{items.length && <List items={items} />}
{/* ✅ 推荐 */}
{items.length > 0 ? <List items={items} /> : null}
总结
Rendering Patterns = 让浏览器和 React 都高效
- SVG 动画 → wrapper transform
- 长列表 → content-visibility
- SSR → hydrate 安全
- 条件渲染 → 明确三元