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 安全
  • 条件渲染 → 明确三元
相关推荐
@PHARAOH1 小时前
WHAT - Vercel react-best-practices 系列(三)
javascript·react.js·ecmascript
今天也要晒太阳4732 小时前
对el-upload的上传文件显示名做长度限制
前端
白兰地空瓶2 小时前
Zustand:若 React 组件是公民,谁来当“中央银行”?—— 打造轻量级企业级状态管理
react.js·typescript
Thomas游戏开发2 小时前
分享一个好玩的:一次提示词让AI同时开发双引擎框架
前端·javascript·后端
NEXT062 小时前
别再折磨自己了!放弃 Redux 后,我用 Zustand + TS 爽到起飞
前端·react.js
donecoding2 小时前
Sass 模块化革命:告别 @import,拥抱 @use 和 @forward
前端·css·代码规范
m0_748252382 小时前
Angular 2 数据显示方法
前端·javascript·angular.js
2501_944711432 小时前
现代 React 路由实践指南
前端·react.js·前端框架
by————组态2 小时前
睿控(Ricon)组态
运维·前端·物联网·信息可视化·组态·组态软件