如何在API路由与getServerSideProps之间共享带TTL的缓存数据
方案1:使用Next.js内置缓存(优先推荐)
Next.js原生提供了跨服务端上下文的全局缓存能力,无需额外依赖,性能最优:
- App Router场景:直接调用原生
fetch请求外部API,设置next.revalidate参数为你的ttl值即可,缓存自动全局共享,在Server Components、Route Handler、服务端函数中调用同个接口会复用缓存,到期自动失效。 - Pages Router场景:用
unstable_cache封装请求逻辑,示例代码:
import { unstable_cache } from 'next/cache' const getX = unstable_cache( async () => { const res = await fetch('外部API地址') return res.json() }, ['unique-key-for-data-x'], // 唯一缓存键 { revalidate: 你的ttl秒数 } )
封装完成后直接在getServerSideProps和API路由中调用getX()即可,自动实现按需拉取、ttl失效、全局缓存共享。
方案2:全局单例LRU缓存(适用于自托管单实例部署)
你之前用类静态属性失效的核心原因是Next.js的模块加载机制,不同服务端上下文加载模块时可能生成独立的类实例,通过将缓存挂载到全局对象可以规避这个问题:
首先安装轻量内存缓存库lru-cache,然后封装工具函数:
import LRU from 'lru-cache' // 挂载到globalThis避免模块隔离/热重载导致的多实例问题 const globalCache = globalThis as unknown as { xCache: LRU<string, any> } if (!globalCache.xCache) { globalCache.xCache = new LRU({ max: 1, ttl: 你的ttl秒数 * 1000 }) } const cache = globalCache.xCache export async function getX() { let x = cache.get('x') if (!x) { x = await fetch('外部API地址').then(res => res.json()) cache.set('x', x) } return x }
该方案纯内存读写,性能和你最初的类静态属性方案一致,解决了实例隔离问题。
方案3:轻量内存存储(适用于多实例/Serverless部署)
如果你的服务部署在多worker、多实例或者Vercel这类Serverless环境,进程内内存本身无法跨实例共享,建议使用本地Redis或者SQLite作为缓存层:SQLite走本地IO性能远高于直接读写普通文本文件,Redis为纯内存操作延迟极低,完全可以满足性能要求。
内容的提问来源于stack exchange,提问作者jannis
相关产品推荐
相关产品推荐

