Next.js 13中notFound()返回200而非404的问题排查
Next.js动态路由notFound()返回200状态码的问题解析与解决
问题原因拆解
当设置export const dynamicParams = false;时,未预生成的路径会直接触发Next.js的静态404处理,服务器直接返回404状态码并渲染not-found.tsx。但移除该配置后进入SSR模式,出现状态码异常的核心原因通常有两个:
notFound()调用时机在客户端:如果资源检查逻辑放在带'use client'指令的客户端组件中,或是通过useEffect等客户端钩子执行,服务器在渲染时已经返回了200状态码的HTML,客户端hydration阶段才触发notFound()切换到404组件,导致网络面板显示200。- 服务器端未正确触发状态码:App Router中,
notFound()只有在服务器组件或服务器路由处理函数(如route.ts)中调用时,才会让服务器返回404状态码。若检查逻辑仅在客户端执行,服务器无法感知资源不存在,自然返回200。
解决方法
将检查逻辑移至服务器组件
把资源存在性检查和notFound()调用放在无'use client'指令的服务器组件中,确保服务器在渲染阶段就能检测到资源不存在,主动返回404状态码:// app/[...slug]/page.tsx(服务器组件) import { notFound } from 'next/navigation'; import { getResourceBySlug } from '@/lib/api'; export default async function SlugPage({ params }: { params: { slug: string[] } }) { const resource = await getResourceBySlug(params.slug.join('/')); if (!resource) { notFound(); // 服务器端调用,自动返回404状态码 } return <div>{resource.content}</div>; }通过服务器路由处理函数强制返回404
如果需要在路由层面统一处理,可在app/[...slug]/route.ts中添加服务器端检查:// app/[...slug]/route.ts import { notFound } from 'next/server'; import { checkResourceExists } from '@/lib/utils'; export async function GET(request: Request, { params }: { params: { slug: string[] } }) { const exists = await checkResourceExists(params.slug.join('/')); if (!exists) { notFound(); // 触发404状态码 } // 资源存在时,返回正常响应(或交由page组件处理) return new Response(null, { status: 200 }); }排查中间件干扰
检查项目中的middleware.ts,确认没有自定义逻辑错误地覆盖了响应状态码,比如将404响应强制改为200的情况。
关键说明
Next.js的notFound()函数本身会自动设置404状态码,但仅在服务器端执行上下文中生效。如果是在客户端调用,只是前端组件的切换,不会改变服务器已经返回的初始响应状态码。
内容的提问来源于stack exchange,提问作者Maciej Wira
相关产品推荐
相关产品推荐

