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

Next.js 13 API路由静态化问题:配置SSR路由获取实时数据

问题

我用Next.js 13、React和Firestore开发Web应用,写了一个API路由从Firestore取数据,并且设置了cache:"no-store"想实现SSR。开发模式一切正常,但构建后Next.js把这个API路由静态化了,返回的是构建时的旧数据。Dashboard页面是SSR且运行正常,但API路由没法实时获取数据。

Dashboard page.jsx中的请求代码:

const getExamDate = async () => {
  const response = await fetch("http://localhost:3000/api/ExamInfo", {
    cache: "no-store",
  });
  const data = await response.json();
  if (data) {
    console.log("fetched again");
  }
  return data;
};

Firestore数据API端点代码:

export async function GET() {
  try {
    const Exams = [];
    const documentInfo = await getDocs(collection(db, "Exams"));
    documentInfo.forEach((doc) => {
      Exams.push(doc.data());
    });
    console.log("API: ", Exams);
    return NextResponse.json({ Exams, status: 200 });
  } catch (error) {
    console.error(error);
    return NextResponse.json(
      { error: "Failed to fetch exam data" },
      { status: 401 }
    );
  }
}

构建结果:

○ /  
├ ○ /api/ExamInfo (static)  
├ λ /Dashboard (SSR)

我现在用了个临时办法:给API的GET方法加request参数并打印URL,强制每次请求都调用API,但这明显不是正确做法,请问怎么正确配置SSR API路由,让它每次请求都获取最新数据?


正确解决方案

要让Next.js 13的API路由每次请求都实时获取数据,有几种标准的可靠方式:

1. 设置dynamic = "force-dynamic"

在API路由文件的最顶部添加这个配置,直接告诉Next.js该路由必须动态执行,禁止静态化:

export const dynamic = "force-dynamic"; // 核心配置

export async function GET() {
  try {
    const Exams = [];
    const documentInfo = await getDocs(collection(db, "Exams"));
    documentInfo.forEach((doc) => {
      Exams.push(doc.data());
    });
    console.log("API: ", Exams);
    return NextResponse.json({ Exams, status: 200 });
  } catch (error) {
    console.error(error);
    return NextResponse.json(
      { error: "Failed to fetch exam data" },
      { status: 401 }
    );
  }
}

配置后,构建结果里的/api/ExamInfo会变成λ(动态)类型,每次请求都会重新执行代码拉取最新的Firestore数据。

2. 添加Cache-Control响应头

在返回响应时设置缓存控制头,明确禁止任何缓存:

export async function GET() {
  try {
    const Exams = [];
    const documentInfo = await getDocs(collection(db, "Exams"));
    documentInfo.forEach((doc) => {
      Exams.push(doc.data());
    });
    console.log("API: ", Exams);
    return NextResponse.json({ Exams, status: 200 }, {
      headers: {
        "Cache-Control": "no-store, max-age=0",
      },
    });
  } catch (error) {
    console.error(error);
    return NextResponse.json(
      { error: "Failed to fetch exam data" },
      { 
        status: 401, 
        headers: { "Cache-Control": "no-store, max-age=0" } 
      }
    );
  }
}

这个HTTP头会告知客户端和服务器不要缓存该响应,确保每次请求都获取最新内容。

3. 使用revalidate: 0

在API路由顶部设置revalidate: 0,效果和dynamic = "force-dynamic"一致,强制每次请求都重新生成响应:

export const revalidate = 0;

export async function GET() {
  // 原有业务代码保持不变
}

关于临时方案的原理

你之前给GET方法加request参数的方式之所以能生效,是因为Next.js会判定该路由依赖请求参数,无法提前静态化,所以自动转为动态路由。但这种方式是间接触发,不如上面的标准配置清晰、可维护。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 18:43:15