NextJS部署Vercel后getServerSideProps行为异常问题
背景概述
路由结构:
/template:加载当前用户所有模板(通过getServerSideProps获取数据)/template/new:用户创建并保存模板的页面/api/save-template:接收前端保存请求、处理数据库存储的API接口
操作流程中,用户保存模板后通过router.push('/template')重定向,但Vercel环境下新模板未显示;本地环境(next dev/next build && next start)则正常。已确认数据库中存在新模板,但Vercel日志无第二次/template请求及getServerSideProps执行记录。
1. 为何重定向后看不到/template的第二次请求及getServerSideProps日志?
这是Vercel的强缓存策略导致的。首次访问/template时,Vercel会缓存页面或getServerSideProps的执行结果;而router.push属于客户端导航,Next.js会优先复用客户端已缓存的页面数据,不会重新触发服务器端的getServerSideProps,因此不会产生新的请求日志。
2. 为何本地环境正常?
本地开发/构建环境默认没有开启Vercel级别的强缓存策略。客户端导航时,Next.js会主动重新调用getServerSideProps拉取最新数据,因此能正常显示新创建的模板。
3. 展示刚创建数据的通用解决方案
以下是几种可行的方案,可根据场景选择:
方案一:强制页面刷新
在router.push后触发页面刷新,绕过客户端缓存,确保getServerSideProps重新执行:
router.push('/template').then(() => window.location.reload())
缺点是会有页面刷新的体验损耗,但能保证数据绝对最新。
方案二:手动更新客户端状态
保存成功后,直接将新模板数据注入客户端的状态管理中(如果/template页面维护了客户端状态),无需等待服务器返回:
// 示例:假设用useState维护模板列表 // 保存接口调用成功后,直接把新模板加入列表 const newTemplate = await fetch('/api/save-template', { method: 'POST', body: JSON.stringify(templateData) }).then(res => res.json()); // 通过状态管理工具(如Zustand/Redux)或Context更新列表 addToTemplateList(newTemplate); router.push('/template');
这种方式无刷新,体验最佳,适合有客户端状态管理的场景。
方案三:禁用页面缓存
在/template页面的getServerSideProps中添加缓存控制头,强制Vercel不缓存页面结果:
export async function getServerSideProps(context) { const templates = await fetchUserTemplates(); // 设置缓存控制,禁止任何缓存 context.res.setHeader( 'Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate' ); return { props: { templates }, }; }
每次客户端导航到/template时,都会触发getServerSideProps重新拉取数据。
方案四:使用增量静态再生(ISR)
如果模板数据更新频率不高,可将/template改为ISR模式,设置较短的重新生成时间:
export async function getStaticProps() { const templates = await fetchUserTemplates(); return { props: { templates }, revalidate: 10, // 每10秒重新生成页面 }; }
缺点是无法实时显示新数据,适合非实时更新的场景。
内容的提问来源于stack exchange,提问作者Daniel Reina

