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
相关产品推荐
相关产品推荐

