上饶市网站建设_网站建设公司_导航菜单_seo优化
2026/1/15 16:51:08 网站建设 项目流程

文章目录

  • 前言
  • 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 只做交互

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询