Next.js 16 PPR:/api/og路由在每次构建时都会输出“需要退出预渲染”
我在Next.js 16项目中启用了部分预渲染(PPR),方法是通过在所有页面注释掉export const dynamic = "force-dynamic" 并在next.config.ts中加入cacheComponents: true。构建成功,所有页面都正确进行预渲染,但在next build过程中会把这个日志打印两次:
OpenGraph image generation failed: Error: Route /api/og needs to bail out of prerendering at this point because it used request.url. at R (app\api\og\route.tsx:60:46)
58 | ...port async function GET(request: NextRequest) {
59 | ...try {
> 60 | ... const { searchParams } = new URL(request.url);
|
^
该路由在处理中会用request.url读取搜索参数,并用request.headers读取动态主机名,因此无法进行静态预渲染。该错误不会导致构建失败,但会使输出变得混乱。
我之前在这个路由上设置了export const runtime = "edge",但已移除。由于这会破坏PPR的初衷,我也不想再添加export const dynamic = "force-dynamic"。
我尝试过:
- 移除export const runtime = "edge" —— 没有变化
- 将读取搜索参数的逻辑移动到处理程序内部(本来就在里面)——没有变化
- 使用try/catch包裹(本来就是这样)——这只是一个预渲染中止,而不是运行时错误
问题:
- 是否有办法在不使用force-dynamic的情况下,显式将单个API路由排除在PPR之外?
- 这只是一个无害的日志,可以被抑制,还是表示有问题?
- OG图像路由是否应放在一个单独的路由组中,在布局层设置export const dynamic = "force-dynamic"?
环境:
- Next.js 16.2.6
- next.config.ts中 cacheComponents: true
- 全局启用了PPR(没有anywhere使用force-dynamic)
- 路由:app/api/og/route.tsx
解决方案
在我的Next.js配置中设置experimental.hideLogsAfterAbort: true。
next.config.ts
const nextConfig: NextConfig = {
cacheComponents: true,
experimental: {
hideLogsAfterAbort: true,
other experiments...
},
};
export default nextConfig;
为什么会这样: 根本原因是cacheComponents: true,而不是PPR或移除force-dynamic。开启该标志后,Next.js会尝试对每个路由进行预渲染,包括API路由。当它在我的OpenGraph处理程序中遇到new URL(request.url) 时,会中止并记录诊断信息。错误信息写着“OpenGraph图像生成失败”,但这其实是误导——它只是一次静态生成中止,并非运行时失败。
hideLogsAfterAbort的作用: 它会抑制对那些确实无法静态预渲染的路由的预渲染中止诊断。你的OpenGraph路由在运行时仍然可以正常工作。唯一的影响是构建输出更干净。
关于PPR与缓存组件的说明: 注释掉force-dynamic并不会开启PPR。真正触发此行为的标志是cacheComponents。如果未来通过experimental.ppr配置开启真正的PPR,同样的修复也适用。
// These are NOT the same:
export const dynamic = "force-dynamic"; // explicit opt-out
cacheComponents: true;