如何在Next.js的getStaticProps和getStaticPath中返回410状态码?
在Next.js Pages Router中实现静态生成/ISR页面返回410状态码
要在保留ISR(增量静态再生)特性的前提下,让动态静态生成页面返回410(Gone)状态码,可采用以下几种方案:
方案一:结合中间件(Middleware)实现全局检测
利用Next.js的Edge中间件,在请求到达页面之前拦截并判断资源是否存在,直接返回410状态码,同时不影响已存在页面的ISR特性。
- 创建项目根目录下的
middleware.js文件:
import { NextResponse } from 'next/server'; // 适配Edge Runtime的资源检测函数(确保无Node.js专属API) async function fetchUser(name) { // 替换为你的实际资源查询逻辑,比如调用Edge兼容的API const res = await fetch(`https://your-api.com/users/${name}`); return res.ok ? await res.json() : null; } export async function middleware(request) { const { pathname } = request.nextUrl; // 提取动态参数(假设页面路径为 /users/[name]) const nameMatch = pathname.match(/^\/users\/([^/]+)$/); if (nameMatch) { const user = await fetchUser(nameMatch[1]); if (!user) { // 资源不存在,返回410状态码 return new NextResponse('资源已永久移除', { status: 410 }); } } // 资源存在,继续请求流程 return NextResponse.next(); } // 配置中间件生效的路径 export const config = { matcher: '/users/:name*', // 匹配你的动态页面路径 };
- 保留原有的
getStaticProps和getStaticPaths配置(包含revalidate):
export async function getStaticProps({ params: { name } }) { const user = await fetchUser(name); // 这里依然保留判断,确保静态生成时的正确渲染 if (!user) { return { props: { statusCode: 410 }, revalidate: 60, }; } return { props: { user }, revalidate: 60, }; } export async function getStaticPaths() { // 你的静态路径生成逻辑 return { paths: [], // 预生成的路径 fallback: 'blocking', // 或 'true',根据需求选择 }; }
优点:
- 完全保留ISR特性,已存在的页面仍会静态生成并自动重新验证
- 服务端直接返回410状态码,爬虫能正确识别
- 无需修改页面组件逻辑
注意:中间件运行在Edge Runtime,确保资源查询逻辑兼容Edge环境(不能使用fs、child_process等Node.js专属模块)
方案二:自定义404页面+服务端状态码设置
利用Next.js的自定义404页面,结合getServerSideProps判断请求资源是否应返回410,动态设置状态码。
- 保留原
getStaticProps中的notFound: true判断:
export async function getStaticProps({ params: { name } }) { const user = await fetchUser(name); if (!user) { return { notFound: true, // 触发404页面 revalidate: 60, }; } return { props: { user }, revalidate: 60, }; }
- 创建
pages/404.js页面,添加服务端逻辑:
export async function getServerSideProps({ req, res }) { const requestPath = req.url; // 提取动态参数(适配你的页面路径) const nameMatch = requestPath.match(/^\/users\/([^/]+)$/); if (nameMatch) { const user = await fetchUser(nameMatch[1]); if (!user) { // 资源永久移除,设置410状态码 res.statusCode = 410; } } return { props: {} }; } export default function CustomErrorPage() { return ( <div> <h1>410 Gone</h1> <p>该资源已永久移除,不会再恢复</p> </div> ); }
优点:
- 无需额外配置中间件,逻辑集中在页面层
- 保留ISR特性,仅当页面触发404时才会执行服务端判断
缺点:
- 所有404请求都会进入该页面的服务端逻辑,可能增加少量服务端负载
方案三:页面组件内结合服务端渲染设置状态码(仅限Next.js 13+ Pages Router)
如果使用Next.js 13+的Pages Router,可在页面组件中直接使用服务器组件特性设置响应状态码:
import { headers } from 'next/headers'; export async function getStaticProps({ params: { name } }) { const user = await fetchUser(name); return { props: { user, isGone: !user }, revalidate: 60, }; } export default function UserPage({ user, isGone }) { if (isGone) { // 直接返回410响应(仅在服务器组件中生效) return new Response('资源已永久移除', { status: 410 }); } return ( <div> <h1>用户:{user.name}</h1> {/* 页面内容 */} </div> ); }
注意:该方案仅适用于Next.js 13+的Pages Router,且页面需为服务器组件(默认即为服务器组件)。
内容的提问来源于stack exchange,提问作者Komeil Mehranfar
相关产品推荐
相关产品推荐

