You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Next.js 13 App Router中显示自定义410页面

在Next.js 13 App Router中实现自定义410页面

Next.js 13 App Router没有像处理404那样内置notFound()函数直接触发410页面,需要手动实现,以下是具体方案:

1. 创建自定义410页面组件

在app目录下新建410/page.js(或自定义路径如app/gone/page.js),编写页面UI并设置410状态码:

export default function GonePage() {
  return (
    <div style={{ padding: '2rem', textAlign: 'center' }}>
      <h1>410 - 资源已永久移除</h1>
      <p>您访问的资源已被永久删除,不会再恢复。</p>
    </div>
  );
}

// 设置页面状态码为410
export async function generateMetadata() {
  return {
    status: 410,
  };
}

2. 在业务路由中触发410

如果某个路由对应的资源已永久删除,在Server Component中判断后直接渲染410组件,并同步设置状态码:

比如在app/blog/[slug]/page.js中:

import GonePage from '@/app/410/page';

// 模拟获取文章数据的函数
async function fetchBlogPost(slug) {
  // 实际业务逻辑:从数据库/API获取数据
  const res = await fetch(`https://your-api.com/posts/${slug}`);
  if (!res.ok) {
    // 假设410状态码表示资源永久移除
    if (res.status === 410) {
      return { isPermanentlyRemoved: true };
    }
    return null;
  }
  return res.json();
}

export default async function BlogPostPage({ params }) {
  const post = await fetchBlogPost(params.slug);

  // 判断资源是否永久移除
  if (post?.isPermanentlyRemoved) {
    return <GonePage />;
  }

  // 资源存在时正常渲染
  return (
    <div>
      <h1>{post.title}</h1>
      <div>{post.content}</div>
    </div>
  );
}

// 同步设置元数据中的状态码
export async function generateMetadata({ params }) {
  const post = await fetchBlogPost(params.slug);
  
  if (post?.isPermanentlyRemoved) {
    return { status: 410 };
  }

  return {
    title: post?.title || '博客文章',
  };
}

3. 用Middleware批量拦截旧路由

如果有一批已永久移除的旧路由,可以通过middleware.js统一拦截并返回410页面:

import { NextResponse } from 'next/server';

export function middleware(request) {
  // 匹配所有需要返回410的旧路由
  const removedPaths = ['/blog/old-post-1', '/blog/old-post-2', '/archive/2022'];
  
  if (removedPaths.includes(request.nextUrl.pathname)) {
    // 重写到自定义410页面,并设置410状态码
    const response = NextResponse.rewrite(new URL('/410', request.url));
    response.headers.set('status', '410 Gone');
    return response;
  }
}

// 指定Middleware生效的路由范围
export const config = {
  matcher: ['/blog/:path*', '/archive/:path*'],
};

注意事项

  • 确保generateMetadata中的状态码设置与页面组件的判断逻辑一致,避免状态码与页面内容不匹配。
  • 如果是静态生成的路由,需要在构建时就确定资源是否永久移除,或使用增量静态再生(ISR)更新状态。

内容的提问来源于stack exchange,提问作者amirhossein

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 17:17:29