Next.js unstable_cache未按预期工作问题求助
问题描述
我无法正确使用unstable_cache。我想缓存那些极少变化但被频繁调用的Prisma查询,但测试时发现,哪怕响应看起来像是来自缓存,实际还是会执行函数调用。
我的测试逻辑是:生成0-2的随机数作为缓存键,对带有4秒延迟的0-510随机数生成函数的结果做缓存。当相同的0-2数字再次出现时,我预期直接返回缓存结果,但实际还是要等函数执行完。
测试代码如下:
import { unstable_cache } from "next/cache"; export const dynamic = "force-dynamic"; import { Suspense } from "react"; export default async function Out() { return ( <div> <h2>Test Unstable Cache</h2> <Suspense fallback="Grabbing random number"> <Test /> </Suspense> </div> ); } async function Test() { const numberUsed = await getRandomInt(2); const cacheValue = `numberUsed_${numberUsed}`; console.log(cacheValue); // Use async/await to fetch and cache data const cacheResponse = await unstable_cache( async () => getRandomInt(510), [cacheValue], { revalidate: 90000 }, )(); console.log(numberUsed + " returns " + cacheResponse); let text = numberUsed + " returns " + cacheResponse; return text; } async function getRandomInt(max) { console.log("miss"); const delay = (ms) => new Promise((res) => setTimeout(res, ms)); await delay(4000); return Math.floor(Math.random() * max); }
问题原因与解决办法
核心问题:force-dynamic 禁用了缓存
你在页面组件顶部声明的export const dynamic = "force-dynamic";会强制页面每次请求都重新渲染,完全绕过Next.js的所有缓存机制,包括unstable_cache。这就是为什么每次都会触发getRandomInt执行的根本原因。
解决步骤
调整
dynamic配置- 如果页面不需要完全动态,直接删除
export const dynamic = "force-dynamic";,默认的auto模式会自动启用缓存。 - 若页面确实需要部分动态内容,可改用
dynamic = "auto"(默认)或dynamic = "force-static"(适合静态为主、少量动态的场景)。
- 如果页面不需要完全动态,直接删除
优化
unstable_cache的使用方式- 建议将缓存函数的定义移出组件渲染逻辑,避免每次组件渲染都重新创建缓存实例,示例代码如下:
import { unstable_cache } from "next/cache"; import { Suspense } from "react"; // 缓存函数定义在组件外部,确保全局唯一 const cachedRandomInt = unstable_cache( async (max) => getRandomInt(max), [], { revalidate: 90000 } ); export default async function Out() { return ( <div> <h2>Test Unstable Cache</h2> <Suspense fallback="Grabbing random number"> <Test /> </Suspense> </div> ); } async function Test() { const numberUsed = await getRandomInt(2); // 调用时传入动态缓存键 const cacheResponse = await cachedRandomInt(510, [`numberUsed_${numberUsed}`]); console.log(`${numberUsed} returns ${cacheResponse}`); return `${numberUsed} returns ${cacheResponse}`; } async function getRandomInt(max) { console.log("miss"); const delay = (ms) => new Promise((res) => setTimeout(res, ms)); await delay(4000); return Math.floor(Math.random() * max); }
额外注意事项
unstable_cache属于实验性API,未来可能存在变更,生产环境使用需谨慎评估。- 用于缓存的Prisma查询需保证是纯函数(相同输入返回相同结果),否则缓存会失效。
内容的提问来源于stack exchange,提问作者Radium Chris
相关产品推荐
相关产品推荐

