首页
/ AutoGPT 前端性能实践:Next.js 跨请求 LRU 缓存(server-cache-lru 规则详解)

AutoGPT 前端性能实践:Next.js 跨请求 LRU 缓存(server-cache-lru 规则详解)

2026-09-06 15:00:46作者:董灵辛Dennis

本文围绕 AutoGPT 仓库内置的 Vercel React 最佳实践规则 server-cache-lru 展开,讲解当 React.cache() 的缓存范围只限于单个请求时,如何用 lru-cache 实现跨请求的数据缓存。读完本文,你可以掌握 LRU 缓存在 Next.js 服务端(Route Handler / Server Component)中的完整落地方式、maxttl 参数的含义,以及在不同运行时环境(共享函数实例 vs 传统 Serverless)下的选型依据。

规则定位:Vercel React 最佳实践中的 server-cache-lru

该规则文件位于 .claude/skills/vercel-react-best-practices/rules/server-cache-lru.md,是 Vercel 工程团队维护的 45 条 React/Next.js 性能优化规则之一,元数据标注如下:

  • title: Cross-Request LRU Caching
  • impact: HIGH(高影响)
  • impactDescription: caches across requests(跨请求缓存)
  • tags: server, cache, lru, cross-request

SKILL.md 的规则优先级体系中,它归属于第 3 优先级分类「Server-Side Performance(服务端性能,HIGH)」,与以下 4 条服务端规则并列:

规则 一句话说明
server-cache-react React.cache() 做单请求内去重
server-cache-lru 用 LRU 缓存做跨请求缓存
server-serialization 最小化 RSC 边界序列化的数据量
server-parallel-fetching 重组组件结构以并行化数据获取
server-after-nonblocking after() 执行不阻塞响应的操作

其中 server-cache-reactserver-cache-lru 是一对互补规则:前者解决「一个请求内重复查询」,后者解决「多个请求间重复查询」。两者配合,构成 Next.js 服务端数据获取的完整缓存策略。

核心问题:React.cache() 的生命周期只有单个请求

规则原文点明了问题的本质:

React.cache() only works within one request. For data shared across sequential requests (user clicks button A then button B), use an LRU cache.

React.cache() 的去重范围被绑定在单次请求的生命周期内。参考同目录的 server-cache-react.md,它的典型用法是:

import { cache } from 'react'

export const getCurrentUser = cache(async () => {
  const session = await auth()
  if (!session?.user?.id) return null
  return await db.user.findUnique({
    where: { id: session.user.id }
  })
})

同一次渲染中,多个组件调用 getCurrentUser() 只会执行一次查询,这是它擅长的场景。但考虑用户交互的真实节奏:用户先点击按钮 A(触发请求 1),紧接着点击按钮 B(触发请求 2)。这两个是顺序执行的独立请求React.cache() 在请求 1 结束后即被丢弃,请求 2 到达时数据必须重新查库。而这两次点击往往在秒级间隔内命中不同端点、却需要同一份数据——这正是 LRU 缓存要填补的空白。

两种缓存的分工可以概括为:

维度 React.cache() LRU Cache(lru-cache
作用域 单个请求内 跨请求(进程/函数实例内)
容量控制 无,随请求销毁 max 条数上限,自动淘汰
时效控制 请求结束即失效 ttl 过期时间
适用场景 同一次渲染内的多次调用去重 用户在短时间内连续操作命中同一份数据

LRU 缓存的完整实现

规则文档给出的参考实现如下(完整继承自 server-cache-lru.md):

import { LRUCache } from 'lru-cache'

const cache = new LRUCache<string, any>({
  max: 1000,            // 最多缓存 1000 个条目,超出后按 LRU 策略淘汰最久未访问项
  ttl: 5 * 60 * 1000   // 每条缓存存活 5 分钟(毫秒),到期自动失效
})

export async function getUser(id: string) {
  const cached = cache.get(id)
  if (cached) return cached

  const user = await db.user.findUnique({ where: { id } })
  cache.set(id, user)
  return user
}

// Request 1: DB query, result cached
// Request 2: cache hit, no DB query

几个关键参数与实现细节值得展开:

  • max: 1000:缓存容量上限。LRU(Least Recently Used,最近最少使用)策略保证超限时淘汰的是最久未被访问的条目,高频数据得以保留。条目数应结合单条数据的内存大小与实例内存上限权衡——本示例按 1000 条用户记录估算。
  • ttl: 5 * 60 * 1000lru-cache 的 TTL 以毫秒为单位。5 分钟的时效与规则建议的使用场景(“within seconds”)匹配:既覆盖用户连续操作的窗口,又限制脏数据暴露时间。注意 TTL 到期后条目在下次 get 时判定失效,不会主动回调清除。
  • 泛型 LRUCache<string, any>:键为用户 ID 字符串,值为用户对象。生产环境建议将值类型收紧为具体实体类型,避免 any 掩盖序列化/字段变更问题。
  • 模块级单例const cache = new LRUCache(...) 必须声明在模块顶层,使同一函数实例内的所有请求共享同一个缓存对象;若放进函数体内,每次调用都会新建空缓存,规则即失效。
  • 读写模式:先 get 命中即返回,未命中再查库并 set 回填。这一「旁路缓存(Cache-Aside)」模式与数据库查询逻辑解耦,可平滑降级为直连数据库。

适用场景判定

规则给出的使用判据是一句话:当用户的顺序操作在数秒内命中多个端点、而这些端点需要同一份数据时,使用 LRU 缓存。典型的如:

  1. 请求 1(页面加载)查询用户资料,结果写入缓存;
  2. 用户在数秒内触发请求 2(按钮点击 / 下拉刷新 / 局部 RSC 更新),同一 getUser(id) 直接从缓存返回,省去数据库往返。

反过来,若两次请求间隔远超 TTL、或数据本身要求强一致(如余额扣减后立即展示),则不应依赖该缓存层,或应将 TTL 收紧到业务可接受的窗口。

运行时环境影响:共享实例 vs 传统 Serverless

规则文档特别区分了两种部署形态下 LRU 缓存的有效性,这是选型时必须确认的前提:

共享函数实例环境(如 Vercel 的 Fluid Compute)

LRU 缓存在此尤为有效:多个并发请求可以复用同一个函数实例,模块顶层的 cache 对象因此在请求间持续存活——无需 Redis 等外部存储即可获得跨请求缓存。缓存的命中率直接取决于实例的复用密度。

传统 Serverless 环境

每次调用(invocation)在相互隔离的环境中运行,模块级缓存在冷启动后随实例销毁,跨进程无法共享。此时文档建议:考虑引入 Redis 等外部存储做跨进程缓存,否则进程内 LRU 只能在单实例的复用窗口内起作用,效果大打折扣。

从源码结构看,判断标准很清晰:只要你的运行时会把多个请求调度到同一进程/实例(长驻容器、Fluid Compute、本地开发服务器),进程内 LRU 就能稳定命中;若每次请求都是独立冷实例,则必须把缓存外置。

仓库佐证:AutoGPT 前端与 lru-cache 生态

  • AutoGPT 平台的前端 autogpt_platform/frontend/package.json 使用 Next.js 15.5.21,属于 RSC(React Server Components)架构,正是 server-cache-reactserver-cache-lru 这类服务端规则的目标环境。
  • 前端锁文件 autogpt_platform/frontend/pnpm-lock.yaml 中可见 lru-cache(10.4.3 / 11.2.4 / 5.1.1 等多个版本)作为 pnpm 生态的传递依赖被广泛引用,印证了 lru-cache 是 Node.js 生态中事实标准的进程内缓存实现,与规则推荐一致。
  • 本仓库当前并未在前端业务代码中直接实例化 LRUCache,该规则文件(连同同目录 44 条规则)的定位是指导后续开发与重构:当你在 AutoGPT 前端新增需要跨请求共享数据的服务端函数(如按 ID 取用户、图、凭据的查询封装)时,可直接套用本文模式。

小结

  • React.cache() 负责请求内去重(MEDIUM 影响),lru-cache 负责跨请求缓存(HIGH 影响),两者按作用域分工,可叠加使用;
  • 落地三要素:模块顶层创建 LRUCache 实例、max 控制容量、ttl 控制时效(毫秒);
  • 适用判据:用户顺序操作在数秒内重复命中同一数据;
  • 环境前提:共享函数实例下进程内缓存即可,传统 Serverless 下需评估是否外置 Redis。
登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
898
5.82 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
596
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
921
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.8 K
1.02 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
519
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
391