
在 Next.js 13+ 的 App Router 中,getServerSideProps 已被废弃且完全不生效;若需确保异步数据获取仅在请求时(而非 next build 构建阶段)执行,必须显式配置 dynamic = "force-dynamic"。
在 next.js 13+ 的 app router 中,`getserversideprops` 已被废弃且完全不生效;若需确保异步数据获取仅在请求时(而非 `next build` 构建阶段)执行,必须显式配置 `dynamic = "force-dynamic"`。
Next.js 的 App Router(即 /app 目录结构)彻底重构了数据获取模型:它不再支持 Pages Router 中的 getServerSideProps、getStaticProps 等导出函数。所有数据获取逻辑需直接写在 page.tsx、layout.tsx 或 route.ts 等路由段文件中,并通过 React Server Components(RSC)的原生 async/await 语法实现服务端渲染。
但一个常见误区是:将 await 调用直接写在 Page 组件顶层,却未控制其执行时机——这会导致 next build 在静态编译阶段尝试执行该异步逻辑(尤其当环境变量未就绪或 API URL 未注入时),从而抛出 Cannot fetch from undefined URL 等运行时错误。
✅ 正确解法:使用 dynamic 路由段配置强制禁用缓存与预渲染
Next.js 提供 dynamic 配置项(位于路由段文件顶层作用域),用于声明该路由段的数据获取行为:
// app/page.tsx
export const dynamic = "force-dynamic"; // 关键:禁用所有缓存,确保每次请求都重新执行
async function Page() {
// ✅ 此处 await 将在每个 HTTP 请求时执行(SSR),不会在 next build 期间触发
const hotels = await hotelService.getAllHotels();
return (
<rootlayout><homepage hotels="{hotels}"></homepage></rootlayout>
);
}
export default Page;
? dynamic = "force-dynamic" 的含义:
- 完全跳过 next build 阶段的静态数据收集(即跳过“collecting page data”);
- 每次用户访问该页面时,服务端都会重新执行组件内的 async 逻辑;
- 等效于 Pages Router 中 getServerSideProps 的语义,但实现机制更底层、更统一。
⚠️ 注意事项:
- dynamic 仅在 page.tsx、layout.tsx、route.ts 等路由段文件中有效,普通 .tsx 组件(如 HomePage.tsx)中设置无效;
- 不要混用旧模式:getServerSideProps 在 App Router 中完全被忽略,即使导出也不会被调用;
- 环境变量需通过 process.env.NEXT_PUBLIC_*(客户端)或 process.env.*(服务端)安全读取;确保 API_BACKEND_ENV 在服务端环境变量中正确定义(如通过 .env.local 或 Vercel 环境配置),否则 hotelService 初始化仍会失败;
- 若需兼顾性能与动态性,可考虑 dynamic = "auto"(默认值,自动判断)或 revalidate: 0(在 fetch 中显式控制),但 force-dynamic 是最明确、最可靠的 SSR 保障方案。
? 总结:
App Router 中没有“构建时不执行、请求时才执行”的魔法函数,而是通过 dynamic = "force-dynamic" + 组件级 async 函数 这一组合,精准表达“始终服务端渲染、绝不预生成”的意图。这是现代 Next.js 数据流设计的核心原则——声明式行为控制,而非隐式生命周期钩子。











