You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NextJS 14部署Vercel后缓存无法正常重新验证问题求助

问题:Vercel部署后unstable_cache缓存重验证失效

问题背景

项目首页展示统计数据,为避免频繁从数据库取数,使用Next.js的unstable_cache实现服务器端缓存,设置60秒自动重验证。本地通过build+start运行时缓存逻辑正常,但部署到Vercel后出现异常:构建后首次请求能获取数据库最新数据,刷新页面后加载的却是几天前的旧缓存。

代码实现

客户端组件(API数据获取)

const [data, setData] = useState<HomePageAllStats>(null as any);

useEffect(() => {
  const fetchData = async () => {
    const response = await fetch(`URL/api/stats`, { cache: 'no-store' });
    const data = await response.json();
    setData(data);
  };

  fetchData();
}, []);

API路由(服务器端缓存逻辑)

export async function GET() {
  try {
    const statsPromise = unstable_cache(getStats, ['stats'], { revalidate: 60 });
    const stats = await statsPromise();
    const mappedCountryStats = mapStats(stats.source);
    const data: HomePageAllStats = {
      totalCount: stats.total,
      countries: mappedCountryStats,
    };
    return Response.json(data);
  } catch (error) {
    console.error('Error getting stats:', error);
    return Response.json({});
  }
}

async function getStats(): Promise<TotalStats> {
  const documentReference = await admin.firestore().collection('stats').doc('total').get();
  return documentReference.data() as TotalStats;
}

问题表现

  • 本地环境:缓存每60秒正常重验证,刷新页面能获取最新数据
  • Vercel部署后:首次请求正常,后续刷新加载旧缓存数据

问题分析与修复方案

1. 放弃实验性的unstable_cache,改用HTTP缓存头

unstable_cache是Next.js实验性API,在Vercel环境下的重验证逻辑存在兼容性问题。推荐直接通过HTTP缓存头控制CDN缓存:

export async function GET() {
  try {
    const stats = await getStats();
    const mappedCountryStats = mapStats(stats.source);
    const data: HomePageAllStats = {
      totalCount: stats.total,
      countries: mappedCountryStats,
    };
    // 设置60秒缓存有效期,同时开启后台异步重验证
    return Response.json(data, {
      headers: {
        'Cache-Control': 's-maxage=60, stale-while-revalidate',
      },
    });
  } catch (error) {
    console.error('Error getting stats:', error);
    return Response.json({}, {
      headers: {
        'Cache-Control': 'no-cache',
      },
    });
  }
}

该方案利用Vercel CDN原生支持的缓存规则,stale-while-revalidate能保证用户快速获取缓存数据,后台自动更新缓存,同时避免恶意频繁调用数据库。

2. 禁用Vercel构建阶段的API缓存

Vercel在构建时会预执行API路由并缓存结果,导致后续请求直接使用构建时的旧数据。可通过添加dynamic配置强制每次请求都运行服务器端代码:

// 在API路由顶部添加
export const dynamic = 'force-dynamic';

export async function GET() {
  // 原有逻辑
}

3. 调整客户端fetch的缓存参数

当前客户端使用cache: 'no-store'会绕过浏览器缓存,但无法影响Vercel CDN缓存。若需确保客户端每次请求都触发CDN的缓存检查,可将参数改为:

const response = await fetch(`URL/api/stats`, { cache: 'reload' });

或保留CDN缓存逻辑,将客户端fetch参数改为cache: 'force-cache',让CDN统一处理缓存与重验证。

4. 切换到App Router的稳定缓存方案

若项目使用Next.js App Router,可直接在服务器组件的fetch中配置重验证,无需unstable_cache:

// 服务器组件中直接获取数据
const res = await fetch('URL/api/stats', { next: { revalidate: 60 } });
const data = await res.json();

该方案是Next.js官方推荐的稳定缓存方式,Vercel对其支持更完善。


内容的提问来源于stack exchange,提问作者Andurit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 15:27:44