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

Next.js 13使用revalidate时需刷新两次才显示数据更新问题

问题

我通过以下REST请求在Next.js页面填充数据(使用版本13.4.13):

// src/app/page.js
const Home = async () => {
  const globalData = await getGlobalData();
  return (
    <main>
      <SomeComponent data={globalData} />
    </main>
  );
};

数据来自数据库,我确认数据库信息已于昨日更新,但页面加载时仍显示旧数据,必须刷新两次后才会展示新数据。此后每次页面加载都会显示新数据,但如果数据库数据在数小时前更新,又需要刷新两次才能看到。

我设置了每60秒刷新一次的逻辑,代码如下:

export const refresh = (seconds = 60) => ({ next: { revalidate: seconds }});

export const getGlobalData = async () => {
  try {
    const res = await fetch(`${myDomain}/api/global`, refresh());
    if (!res.ok) {
      console.log('Failed');
      return {};
    }
    return await res.json();
  } catch (e) {
    console.log(`Connection refused`);
  }
  return {};
};
分析与解决方案

核心原因

  1. Next.js静态缓存机制:App Router默认会预渲染页面并生成静态缓存。第一次刷新时,Next.js先返回缓存的旧页面,同时在后台触发重新验证流程;第二次刷新时,新生成的缓存才会生效,所以能看到最新数据。
  2. revalidate配置的局限性:60秒的重新验证周期是从页面首次生成或上次验证完成开始计算的。如果数据库更新时,缓存还没到自动刷新的时间点,就不会主动拉取新数据,必须手动刷新触发验证。

解决办法

  • 强制动态渲染:如果需要每次页面加载都获取最新数据,直接在page.js顶部添加动态渲染配置,跳过静态缓存:
    // src/app/page.js
    export const dynamic = 'force-dynamic';
    
    const Home = async () => {
      const globalData = await getGlobalData();
      return (
        <main>
          <SomeComponent data={globalData} />
        </main>
      );
    };
    
  • 调整fetch的缓存策略:如果想保留部分缓存特性,但需要按需获取最新数据,可以把fetch的revalidate设为0,让每次请求都拉取最新数据:
    export const getGlobalData = async () => {
      try {
        const res = await fetch(`${myDomain}/api/global`, { next: { revalidate: 0 } });
        if (!res.ok) {
          console.log('Failed');
          return {};
        }
        return await res.json();
      } catch (e) {
        console.log(`Connection refused`);
      }
      return {};
    };
    
  • 手动触发缓存刷新:如果数据库更新时有触发机制(比如webhook),可以调用Next.js的revalidatePath API手动生成新缓存,不用等自动revalidate或手动刷新:
    在API路由或数据库更新的处理逻辑中添加:
    import { revalidatePath } from 'next/cache';
    
    // 数据库更新完成后调用该函数
    async function triggerCacheRefresh() {
      revalidatePath('/'); // 重新生成首页的缓存
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 15:46:32