news 2026/4/16 14:16:44

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
WHAT - Vercel react-best-practices 系列(二)

文章目录

  • 前言
  • Guidelines
  • High-Impact Server
    • 1. Use React.cache() for per-request deduplication
      • 核心问题
      • 反例:同一请求,多次 fetch
      • 推荐:`React.cache`
      • 实际发生了什么?
      • 适合 cache 的内容
      • 一句话总结
    • 2. Use LRU cache for cross-request caching
      • 核心问题
      • 典型场景
      • 反例:每个请求都重新算
      • 推荐:LRU Cache
      • 和 React.cache 的关系(非常重要)
      • 单请求和跨请求概念
    • 3. Minimize serialization at RSC boundaries
      • 核心问题
      • 反例:传整个对象
      • 推荐:只传必要字段
      • 更进一步:Server 端消化逻辑
      • 一个非常重要的原则
    • 4. Parallelize data fetching with component composition
      • 反例:集中式 data fetching
      • 推荐:组件各自 fetch
      • 实际发生了什么?
  • 把两部分合在一起看
    • 第一部分:控制时间线
    • 第二部分:控制重复 & 边界
  • 一句话总结(Vercel Server 思维)

前言

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 中的实际收益

High-Impact Server

这是系列的第二部分。

这一部分**已经进入 Vercel / React Server Components 的“真·内功区”**了。它解决的不是「代码好不好看」,而是:

同一请求内别算两遍、不同请求别老算、别在 RSC 边界浪费、让组件结构天然并行

1. Use React.cache() for per-request deduplication

同一个请求里,只算一次

核心问题

同一次页面请求中:

  • 多个组件
  • 多个层级
  • 多次调用同一个数据函数

会被重复执行

反例:同一请求,多次 fetch

asyncfunctiongetUser(){returnfetch('/api/user').then(r=>r.json())}
// Header.tsxconstHeader=async()=>{constuser=awaitgetUser()return<div>{user.name}</div>}// Sidebar.tsxconstSidebar=async()=>{constuser=awaitgetUser()return<Avatar user={user}/>}

结果:

  • 同一个请求
  • 发了2 次/api/user
  • 纯浪费

推荐:React.cache

import{cache}from'react'exportconstgetUser=cache(async()=>{returnfetch('/api/user').then(r=>r.json())})
// Header / Sidebar 仍然各自调用

实际发生了什么?

  • 第一次调用:真正执行
  • 后续调用:直接复用结果
  • 作用域:单个请求(request-scoped)

不会跨用户、不会脏数据


适合 cache 的内容

  • 用户信息
  • 权限 / role
  • feature flags
  • 请求上下文数据

不适合:

  • 强依赖实时性的(秒级行情)
  • 非纯函数(依赖时间、随机数)

一句话总结

React.cache()=request-level memoization


2. Use LRU cache for cross-request caching

不同请求之间复用结果

核心问题

React.cache()只在单次请求有效

但有些数据:

  • 变化不频繁
  • 计算成本高
  • 用户之间通用

应该跨请求缓存

典型场景

  • 产品配置
  • 权限模型
  • 城市 / 国家列表
  • Markdown → HTML
  • OpenAPI schema

反例:每个请求都重新算

asyncfunctiongetConfig(){returnexpensiveCompute()}

推荐:LRU Cache

importLRUfrom'lru-cache'constcache=newLRU<string,any>({max:500,ttl:1000*60*5,// 5 分钟})exportasyncfunctiongetConfig(){constcached=cache.get('config')if(cached)returncachedconstdata=awaitexpensiveCompute()cache.set('config',data)returndata}

和 React.cache 的关系(非常重要)

能力React.cacheLRU
作用范围单请求跨请求
生命周期request进程
适合数据user / ctx公共数据
安全性极高需注意

真实项目中:经常一起用

exportconstgetUser=cache(async(id)=>{returnuserLRU.get(id)??fetchAndSet(id)})

如果你还是无法直接理解单请求和跨请求的区别,请继续阅读下面这部分内容。

单请求和跨请求概念

React.cache = 只在「这一次页面请求」里生效
LRU cache = 在「多次页面请求」之间生效

一、什么叫「单请求(per-request)」?

在 Next.js / RSC 中:

一次浏览器请求一个页面 = 一次 Server Rendering 请求 = 一个 React Server 渲染上下文

例如:

用户 A 打开 /dashboard ← 请求 #1 用户 A 刷新 /dashboard ← 请求 #2 用户 B 打开 /dashboard ← 请求 #3

3 个请求是完全独立的

二、React.cache:为什么叫「单请求」?

看代码

import{cache}from'react'exportconstgetUser=cache(async(id)=>{console.log('fetch user',id)returndb.user.find(id)})

同一次请求

constHeader=async()=>{constuser=awaitgetUser(1)}constSidebar=async()=>{constuser=awaitgetUser(1)}

实际输出

fetch user 1 ✅ 只打印一次

原因:

  • React 在「当前请求上下文」里
  • 维护了一张cache map
  • key = 函数 + 参数
  • 请求结束 → cache 自动销毁

换个请求会怎样?

用户刷新页面
fetch user 1 ❗️又打印了一次

也就是说React.cache 不会跨请求

三、为什么 React.cache 不能跨请求?(非常重要)

因为安全 & 正确性。如果能跨请求,会发生什么?

用户 A 请求 → getUser(1) → 缓存 用户 B 请求 → 复用了 A 的 user

严重数据泄露

所以 React.cache 的设计目标是:

避免同一次渲染中重复计算

❌ 不是做“数据缓存系统”

四、LRU cache:什么叫「跨请求」?

LRU 是什么?

进程级内存缓存

constcache=newLRU({max:100,ttl:1000*60,})

它存在于:

  • Node.js 进程内存
  • 不会因请求结束而清空

多次请求会命中同一份缓存:

exportasyncfunctiongetConfig(){if(cache.has('config')){returncache.get('config')}constdata=awaitloadConfig()cache.set('config',data)returndata}
请求 #1 → loadConfig() 请求 #2 → 命中 cache 请求 #3 → 命中 cache

这就是“跨请求”

六、什么时候用哪个?(直接可用表)

场景React.cacheLRU
同一页面多组件用 user
防止同请求重复 fetch
公共配置
城市列表
用户私有数据⚠️
跨用户共享数据

七、为什么这和 RSC 特别相关?

因为在 RSC 中:

  • 组件 = async 函数
  • 同一个函数会被多次调用
  • 调用顺序由 React 调度
  • 很难保证只调用一次

一句话帮你“刻进脑子里”:

React.cache:React 帮你去重

LRU:你帮服务器省钱

3. Minimize serialization at RSC boundaries

别在 Server → Client 边界传大对象

核心问题

Server Component → Client Component:

  • 数据会被JSON 序列化
  • 再反序列化
  • 再进入 hydration

大对象 = 性能杀手

反例:传整个对象

// Server Componentconstuser=awaitgetUser()return<ClientProfile user={user}/>
// user = { id, name, email, roles, permissions, history, ... }

推荐:只传必要字段

return(<ClientProfile userId={user.id}name={user.name}/>)

更进一步:Server 端消化逻辑

把逻辑丢给 Client

<ClientChart rawData={bigData}/>

Server 先算好

constchartData=processChartData(bigData)<ClientChart data={chartData}/>

一个非常重要的原则

Client Component = 交互

Server Component = 计算 + IO

4. Parallelize data fetching with component composition

组件结构 = 并行结构

这是RSC 最“反直觉但最强”的能力

反例:集中式 data fetching

constPage=async()=>{constuser=awaitgetUser()constposts=awaitgetPosts()conststats=awaitgetStats()return(<><Profile user={user}/><PostList posts={posts}/><Stats stats={stats}/></>)}

隐性问题:

  • Page 被迫成为“数据瓶颈”
  • Suspense 不好拆
  • 并行受限

推荐:组件各自 fetch

constProfile=async()=>{constuser=awaitgetUser()return<div>{user.name}</div>}constPostList=async()=>{constposts=awaitgetPosts()return<ul>{/* ... */}</ul>}constStats=async()=>{conststats=awaitgetStats()return<Chart data={stats}/>}
constPage=()=>{return(<><Suspense fallback={<ProfileSkeleton/>}><Profile/></Suspense><Suspense fallback={<PostSkeleton/>}><PostList/></Suspense><Suspense fallback={<StatsSkeleton/>}><Stats/></Suspense></>)}

实际发生了什么?

  • React同时启动所有组件的 async
  • 自动并行
  • 自动 streaming
  • 自动局部 fallback

你只负责组件拆分,React 负责调度

把两部分合在一起看

第一部分:控制时间线

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

  • Start promises early
  • Promise.all
  • Suspense

第二部分:控制重复 & 边界

  • cache(请求内)
  • LRU(请求间)
  • 减少 RSC payload
  • 组件并行

两者叠加,才是 Vercel 推荐的“正确打开方式”


一句话总结(Vercel Server 思维)

数据靠近组件

缓存靠近计算

并行来自结构

Client 只做交互

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 11:12:17

基于uni-app的儿童安全教育平台

第三章 系统分析 3.1 系统设计目标 儿童安全教育平台主要是为了方便管理儿童安全教育的信息。也是为了更好的让管理员进行更好存储所有数据信息及快速方便的检索功能&#xff0c;对系统的各个模块是通过许多今天的发达系统做出合理的分析来确定考虑用户的可操作性&#xff0c;遵…

作者头像 李华
网站建设 2026/4/16 12:46:53

【拯救HMI】HMI国际化设计:多语言界面的十大注意事项

在全球化制造的今天&#xff0c;一台由中国设计的设备可能安装在德国工厂&#xff0c;由越南操作员使用。HMI的国际化&#xff08;i18n&#xff09;与本地化&#xff08;L10n&#xff09;设计&#xff0c;是产品成功进入国际市场的“通行证”&#xff0c;其核心目标是消除语言障…

作者头像 李华
网站建设 2026/4/16 11:00:36

5 款 AI 写论文哪个好?实测宏智树 AI:毕业论文的 “学术全能王”

作为深耕论文写作科普的教育测评博主&#xff0c;每年毕业季后台都会被 “AI 写论文工具怎么选” 的提问淹没。市面上的 AI 论文工具五花八门&#xff0c;但真正能兼顾专业性、合规性与实用性的却寥寥无几。为此&#xff0c;我实测了 5 款当下热门的真实 AI 写论文工具 ——宏智…

作者头像 李华
网站建设 2026/4/16 11:09:40

国家战略急需!网安工程师年薪真能过百万?好不好入行一篇说透!

针对时下大火的“网络安全工程师”,网络出现不少相关报导和信息: 下面就来跟大家分享一下网络安全工程师工资待遇&#xff0c;给大家作为一个参考。 不同工作经验的待遇水平 其中应届生工资&#xffe5;6070&#xff0c;1-3年工资&#xffe5;8820&#xff0c;3-5年工资&…

作者头像 李华
网站建设 2026/4/16 11:15:55

2026年中国就业格局:在技术革命与结构重塑中破局

2026年的中国就业市场&#xff0c;正处在多重变革力量的交汇点&#xff1a;应届毕业生规模持续高位运行&#xff0c;生成式AI全面渗透加速岗位迭代&#xff0c;“35岁门槛”的隐形壁垒尚未完全消解。这场交织着人口结构、技术浪潮与社会观念的就业压力测试&#xff0c;不仅牵动…

作者头像 李华
网站建设 2026/4/16 11:11:10

基于Django的书刊商城系统设计与实现

基于Django的书刊商城系统设计与实现 一、系统开发背景与意义 在数字化阅读普及的当下&#xff0c;传统书刊销售仍面临渠道分散、选品效率低、库存管理难等问题。线下书店受地域限制&#xff0c;书籍品类有限&#xff1b;现有线上平台多侧重综合电商&#xff0c;缺乏针对书刊…

作者头像 李华