cal.diy(cal.com)中的服务端性能实践:用 React.cache() 做请求级去重

发布时间:2026/10/27 15:45:35

cal.diy(cal.com)中的服务端性能实践:用 React.cache() 做请求级去重 cal.diycal.com中的服务端性能实践用 React.cache() 做请求级去重【免费下载链接】cal.diyScheduling infrastructure for absolutely everyone.项目地址: https://gitcode.com/GitHub_Trending/ca/cal.diy在 Next.js / React Server Components 应用中同一个页面请求内往往会有多个组件分别发起相同的认证查询或数据库读取造成重复的 DB 访问。本文基于 cal.diy 仓库内置的 server-cache-react 规则文档Vercel 出品、MIT 许可的 React 性能规则库中的一条 MEDIUM 级规则讲解React.cache()的请求级去重机制、适用边界并结合 cal.com 源码中真实的unstable_cache封装实现说明“请求内去重”与“跨请求缓存”在工程上如何各取所需。一、规则出处Vercel React Best Practices 规则库中的位置cal.diy 仓库在 agents/skills/vercel-react-best-practices 中内置了一份由 Vercel Engineering 维护的 React / Next.js 性能优化规则集共 45 条规则、8 个分类按影响面排序见 SKILL.md 中的优先级表优先级分类影响前缀1消除瀑布流CRITICALasync-2打包体积优化CRITICALbundle-3服务端性能HIGHserver-4客户端数据获取MEDIUM-HIGHclient-5~8重渲染 / 渲染 / JS / 高级模式MEDIUM ~ LOWrerender-等server-cache-react属于第 3 类“Server-Side Performance服务端性能”规则文件自身元信息frontmatter标注为标题Per-Request Deduplication with React.cache()影响等级MEDIUMimpactDescription: deduplicates within request标签server, cache, react-cache, deduplication完整的规则汇编版见 AGENTS.md 的 3.4 节约 L715-L735与本规则文件内容一致它的姊妹规则 server-cache-lru.md 则解决“跨请求缓存”问题。两条规则合起来覆盖了服务端数据获取的两种去重/缓存场景。二、规则要解决的问题同一请求内的重复查询规则文档给出的核心结论是一句话用React.cache()做服务端请求级去重收益最大的是认证authentication和数据库查询database queries这类场景。典型痛点是一个 RSC 页面中页面组件、侧边栏、导航栏各自独立地调用“获取当前用户”逻辑若该逻辑内部要await auth()拿会话再查一次数据库那么同一个 HTTP 请求内就会打出多次完全相同的查询。React.cache()的作用是把这类函数在“单次请求的生命周期内”记忆化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()只会真正执行一次查询。第二个及之后的调用直接复用第一次的结果对异步函数而言React 缓存的是返回的 Promise同一请求内并发调用共享同一个 Promise从而把 N 次会话解析 N 次findUnique收敛为 1 次。几个值得注意的机制细节它是“记忆化”而不是“缓存”React.cache()不引入任何过期时间、容量上限或持久化记忆化作用域就是一次渲染/一次请求请求结束即失效。因此它不承担“加速跨请求访问”的职责——这正是需要 LRU 的原因见第四节。适合无参或纯参函数规则示例中的getCurrentUser不接收参数。记忆化以参数身份为键参数来自不可变来源如当前请求内的稳定值时效果最确定带复杂可变参数的函数需谨慎评估。对认证链路的意义auth()这类函数通常内部包含 token 校验、会话存储读取甚至数据库查询是页面中扇出最广的公共依赖天然适合包一层cache()。三、边界请求内去重 vs 跨请求缓存同属server-分类的 server-cache-lru.md 明确划出了React.cache()的边界React.cache()only works within one request. For data shared across sequential requests用户先点了按钮 A、又点了按钮 B两个连续端点需要同一份数据use an LRU cache.该规则给出的 LRU 实现范式影响等级 HIGHimpactDescription: caches across requestsimport { LRUCache } from lru-cache const cache new LRUCachestring, any({ max: 1000, ttl: 5 * 60 * 1000 // 5 minutes }) 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适用条件是“用户在数秒内的连续操作会命中多个端点、且这些端点需要同一份数据”。规则同时指出了部署形态对 LRU 有效性的影响在函数实例可被并发请求共享的托管运行时中进程内 LRU 天然跨请求生效而在传统 serverless 中每次调用相互隔离跨进程缓存则需要 Redis 一类的共享存储。由此可以整理出清晰的选型表维度React.cache()LRU进程内/共享存储作用域单次请求跨请求受 TTL / 容量约束过期机制无请求结束即失效TTL 容量上限典型场景页面内多组件重复取数、认证解析连续操作命中多端点的同一数据部署约束无实例隔离时需外置存储四、cal.com 源码中的对照实践unstable_cache 封装从源码结构看cal.diy 的 Web 应用Next.js并没有直接依赖React.cache()而是把“请求去重/缓存”建立在 Next.js 的unstable_cache之上并做了仓库级的统一封装。这条实践链可以作为规则落地方式的真实参照。4.1 仓库级封装packages/lib/unstable_cachepackages/lib/unstable_cache/unstable_cache.ts 对next/cache的unstable_cache做了一层包装核心是解决序列化问题unstable_cache要求函数返回值可 JSON 序列化/** * This implementation is adapted from https://github.com/vercel/next.js/issues/51613#issuecomment-1892644565. * It is a wrapper around unstable_cache that adds serialization and deserialization */ import { unstable_cache } from next/cache; import { parse, stringify } from superjson; export const cache T, P extends unknown[]( fn: (...params: P) PromiseT, keys: Parameterstypeof unstable_cache[1], opts: Parameterstypeof unstable_cache[2] ) { const wrap async (params: unknown[]): Promisestring { const result await fn(...(params as P)); return stringify(result); }; const cachedFn unstable_cache(wrap, keys, opts); return async (...params: P): PromiseT { const result await cachedFn(params); return parse(result); }; };可以看到封装的要点入参以数组形式收集unstable_cache的键机制要求参数可序列化且多个参数需打包成单一数组参数传入出参用superjson的stringify/parse往返从而支持Date等原生类型。仓库内还有 getInstallCountPerApp.ts 等使用该封装的业务缓存函数。4.2 业务示例团队计划校验的缓存与失效apps/web/app/cache/membership.ts 展示了完整的“缓存 标签失效”闭环use server; import { MembershipRepository } from calcom/features/membership/repositories/MembershipRepository; import { NEXTJS_CACHE_TTL } from calcom/lib/constants; import { revalidateTag, unstable_cache } from next/cache; const CACHE_TAGS { HAS_TEAM_PLAN: MembershipRepository.hasAnyAcceptedMembershipByUserId, } as const; export const getCachedHasTeamPlan unstable_cache( async (userId: number) { const hasTeamPlan await MembershipRepository.hasAnyAcceptedMembershipByUserId(userId); return { hasTeamPlan: !!hasTeamPlan }; }, [getCachedHasTeamPlan], { revalidate: NEXTJS_CACHE_TTL, tags: [CACHE_TAGS.HAS_TEAM_PLAN], } ); export const revalidateHasTeamPlan async () { revalidateTag(CACHE_TAGS.HAS_TEAM_PLAN, max); };配套的参数与取值均有仓库依据revalidate取自常量NEXTJS_CACHE_TTL在 packages/lib/constants.ts 中定义为3600秒即 1 小时。tags缓存标签使用“仓库名 方法名”命名如MembershipRepository.hasAnyAcceptedMembershipByUserId便于定位缓存归属。失效方式revalidateTag(tag, max)将缓存 TTL 直接推进到最大即立刻失效——“读多写少 变更时定向失效”的组合而不是无差别清缓存。4.3 与规则的关系从源码结构看cal.com 的选择与规则文档并不矛盾而是分层互补React.cache()规则server-cache-react解决的是同一请求内的重复调用是 React 运行时的记忆化unstable_cache 封装 revalidateTagcal.com 现状解决的是跨请求的重复数据获取缓存键含函数键与参数userId带 TTL 与定向失效。也就是说若一个页面在同一请求内多处需要hasAnyAcceptedMembershipByUserId的结果unstable_cache在请求内同样只查一次库第二次命中缓存而跨请求的重复读取则完全由revalidateTTL 覆盖。这正是“请求级去重”与“跨请求缓存”两种手段在真实大型 Next.js 应用中如何协同的例证。五、落地建议小结结合规则文档与仓库实践可以给出可操作清单优先包装高频公共依赖会话/认证解析、当前用户查询、组织/团队读取等扇出最广的函数是React.cache()的第一梯队候选规则原文认证与数据库查询受益最大。认清作用域它只对单次请求内的多次调用去重请求之间零共享不要把业务正确性建立在“它缓存了结果”上。异步函数放心用cache()包裹async函数时同一请求内的并发调用共享同一个 Promise不会各自开查询。跨请求需求另选方案连续操作命中多端点、且数据在数秒内可复用用带 TTL 与容量上限的 LRU见 server-cache-lru.mdNext.js 应用也可直接使用unstable_cacherevalidateTag的仓库式封装参照 unstable_cache 封装 与 membership 缓存。缓存键与失效策略要显式无论哪种缓存都建议像 cal.com 那样为每个缓存定义命名标签并在数据变更点如成员关系变化调用定向失效避免依赖 TTL 自然过期造成的数据陈旧窗口。参考路径规则原文.opencode/skill/vercel-react-best-practices/rules/server-cache-react.md规则库总览.opencode/skill/vercel-react-best-practices/SKILL.md、汇编版 .opencode/skill/vercel-react-best-practices/AGENTS.md姊妹规则.opencode/skill/vercel-react-best-practices/rules/server-cache-lru.md仓库实践packages/lib/unstable_cache/unstable_cache.ts、apps/web/app/cache/membership.ts、packages/lib/constants.ts【免费下载链接】cal.diyScheduling infrastructure for absolutely everyone.项目地址: https://gitcode.com/GitHub_Trending/ca/cal.diy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/10/27 3:35:30

SVM实战:银行客户流失预测完整流程与调参指南

简介:压缩包以银行客户流失预测为案例,完整展示支持向量机(SVM)算法在分类问题上的落地流程,适合机器学习初学者、金融数据分析人员及有课程设计需求的学生。压缩包内共4个文件,包括2个CSV数据集、1个Pytho…

2026/10/26 9:38:57

简单并差集在学生管理系统中的应用

在最近的学习中,我对并查集学得一般,懂其原理,但用得不深,不过在最近Java的期末项目里,我的主题是高考模式下的学生成绩管理系统,我的思考就停留在了新高考的312的选科目上,那是不是同组合的人要…

2026/10/27 17:49:15

KITE框架中Upcycle与YOCO的协同扩容原理与工程实践

1. 为什么“LLM扩容”不是简单堆显卡——KITE框架里的范式迁移本质“LLM扩容”这四个字,现在听上去像一句行业黑话。很多人第一反应是:加卡、扩集群、调batch size、上更大参数量模型——仿佛只要算力够猛,一切问题自动消解。但我在KITE项目组…

2026/10/27 17:49:15

YOLOv12在条形码检测中的实践与优化

1. 项目概述:当YOLOv12遇上条形码检测去年在给某物流企业做技术咨询时,他们提出一个痛点需求:仓库扫码枪的漏读率高达15%,特别是在包裹堆叠、条形码污损的情况下。当时我们尝试用传统OpenCV方案改进,效果提升有限。直到…

2026/10/27 17:49:15

51单片机数字钟Proteus仿真:定时器动态扫描与状态机课设全解析

简介:51单片机数字电子钟proteus仿真资料包,面向数字电子技术课程设计及51单片机入门学习者,提供一套完整可运行、可调试的电子钟实现方案。设计基于1602液晶屏实时显示时、分、秒,具备时分秒分别校准(支持加一/减一调…

2026/10/27 17:49:15

深度学习训练-推理不匹配问题与学习率调度优化

1. 问题背景与核心挑战在深度学习模型训练过程中,我们常常会遇到一个棘手的问题:模型在训练集上表现优异,但在实际推理(inference)阶段却出现性能下降。这种现象被称为"训练-推理不匹配"(Trainin…

2026/10/27 17:49:14

跨模型自动扩缩容:LLM服务架构的范式转移

1. 这不是“弹性伸缩”的简单升级,而是LLM服务架构的范式转移 你有没有遇到过这样的场景:团队里三组人同时在用同一个大模型API——A组跑推理任务,B组在做微调验证,C组在压测新提示词。结果A组突然流量激增,B组的微调任…

2026/10/27 17:38:49

AI视频批量生成技术:分布式算力与轻量化推理引擎解析

1. 项目概述:AI视频批量生成的技术革命去年双十一大促期间,某头部电商团队用传统方式制作500条商品视频,8人团队耗时两周完成。而今年使用易元AI后,同等工作量仅需1名运营人员操作10小时——这个真实案例揭示了AI视频批量生成正在…

2026/10/27 14:24:03

全国计算机二级C语言真题PDF高效刷题指南

简介:这份PDF是全国计算机二级C语言考试的试题与答案解析,专为备考二级C语言的考生准备。内容涵盖C语言特点与设计理念、程序基本组成单位、main函数执行流程、函数嵌套调用规则、标识符命名规范、整型实型字符型数据类型、八进制十六进制数合法形式、运…

2026/10/27 9:34:54

requests+BeautifulSoup:爬虫抓取h1标题的入门实战指南

简介:一份以实战为导向的Python爬虫入门资源,面向具备基本编程基础、希望快速掌握网络数据抓取的初学者,可解决从零编写简单爬虫的常见困惑。实例以requests库发送HTTP请求、BeautifulSoup解析HTML文档,完整演示从网页中提取 标题…

2026/10/27 0:59:21

递推最小二乘参数辨识MATLAB编程:二阶系统与渐消记忆实现

简介:这是一篇面向控制系统、信号处理与机器学习等领域学习者的最小二乘参数辨识程序说明文档。资源共包含一个docx格式文档,压缩包大小七十八KB,内容围绕递推最小二乘算法和渐消记忆最小二乘算法展开:先构造一个极点位于单位圆内…

2026/10/27 0:02:28

WorkBuddy_新建任务与工作模式19_“模式选错”的典型代价

“模式选错”的典型代价 摘要 在软件工程中,设计模式、架构模式、并发模式乃至团队协作模式的选择,往往在项目早期就决定了后续的开发效率和维护成本。本文通过多个真实场景,剖析“模式选错”带来的典型代价——包括返工成本、技术债务累积、…

2026/10/27 0:02:28

WorkBuddy_新建任务与工作模式20_新手推荐路径

新手推荐路径 摘要 在 AI 辅助开发工具快速普及的今天,新手面对最多的困惑往往不是"工具够不够强",而是"我该从哪一步开始用"。本文提出一条经过实践验证的三阶段学习路径:先从 Ask(问答式交互)起…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑