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 安全
  • 条件渲染 → 明确三元
相关推荐
骑着蜗牛撵大象3277 分钟前
豆包 Seed 驱动的记账智能体:从拍票抽取到月报生成的全链路落地记录
java·前端·javascript·结构化输出·豆包seed·多模态识别·记账系统
溪语流沙9 分钟前
【Web全栈进阶】前端世界观:现代工具链与框架为什么存在
前端·javascript·vue.js
kyriewen31 分钟前
我逐个测了 JSON.stringify 的 7 个坑:第 1 个就在丢数据
前端·javascript·程序员
积流成海1 小时前
用代码实现哈希计算器:Web Crypto API 实战
前端·算法·哈希算法·哈希函数·盘子工具站
data analyse 4561 小时前
服务端访问日志聚合 PV 与 UV 怎么实现?日志采集与口径设计
大数据·前端·数据分析
song5011 小时前
React Native for OpenHarmony 实战:三方库 react-native-ratings 的鸿蒙化适配指南
javascript·react native·react.js·分类·harmonyos
JavaGuide1 小时前
DeepSeek Harness 重磅更新,Codex、Claude Code 子智能体进官方插件列表了,还有 Git 工作树和思考翻译!
前端·后端
小羊没烦恼!1 小时前
OS X 上使用.NET开发应用程序
开发语言·前端·数据库·人工智能·c#·策略模式
Eiceblue2 小时前
使用 Python 实现 Excel 行列转置(保留单元格样式)
前端·python·excel
西西学代码2 小时前
像素和颜色之间的转换(Flutter)
前端·javascript·flutter