WHAT - Vercel react-best-practices 系列(四)

文章目录

前言

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
  • 会严重影响性能,尤其在大量节点或复杂图形中

反例:直接动画

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 安全
  • 条件渲染 → 明确三元
相关推荐
GIS之路12 小时前
ArcGIS Pro 中的 notebook 初识
前端
JavaGuide12 小时前
7 道 RAG 基础概念知识点/面试题总结
前端·后端
ssshooter12 小时前
看完就懂 useSyncExternalStore
前端·javascript·react.js
格砸13 小时前
从入门到辞职|从ChatGPT到OpenClaw,跟上智能时代的进化
前端·人工智能·后端
Live0000014 小时前
在鸿蒙中使用 Repeat 渲染嵌套列表,修改内层列表的一个元素,页面不会更新
前端·javascript·react native
柳杉14 小时前
使用Ai从零开发智慧水利态势感知大屏(开源)
前端·javascript·数据可视化
兆子龙14 小时前
从高阶函数到 Hooks:React 如何减轻开发者的心智负担(含 Demo + ahooks 推荐)
前端
狗胜14 小时前
测试文章 - API抓取
前端
三小河14 小时前
VS Code 集成 claude-code 教程:告别海外限制,无缝对接国内大模型
前端·程序员