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 安全
  • 条件渲染 → 明确三元
相关推荐
angerdream6 分钟前
Android手把手编写儿童手机远程监控App之agentweb如何实现全屏
前端
星栈15 分钟前
10 分钟跑起第一个 Dioxus 应用:`dx` CLI、`rsx!` 和热更新好不好用
前端·rust·前端框架
奋斗吧程序媛28 分钟前
补充一个小知识点:有关@click.native
前端·vue.js
触底反弹37 分钟前
🚀 手把手用 HTML5 Canvas 从零打造飞机大战游戏,代码全开源!
前端·javascript·canvas
DJ斯特拉39 分钟前
axios快速使用
开发语言·前端·javascript
还有多久拿退休金42 分钟前
Ant Design Tree 搜索定位避坑指南:虚拟滚动下如何实现高亮与精准定位
前端·react.js
小月土星44 分钟前
CSS 3D 从入门到炫技:手把手教你写一个旋转立方体
前端·css
Hilaku1 小时前
AI 写代码越快,为什么 Code Review 越不能省?
前端·javascript·程序员
sugar__salt2 小时前
从网页小游戏到数据可视化:掌握 HTML5 Canvas 核心能力
前端·信息可视化·html5
北极星日淘2 小时前
前端 i18n 中日双语交互 + 翻译客服接口联动方案|日系海淘平台中文友好化开发实战
前端·交互