跳到内容

not-found.js

Next.js 提供了两种处理未找到情况的约定

  • not-found.js:当你在一个路由段中调用 notFound 函数时使用。
  • global-not-found.js:用于为你的整个应用程序中不匹配的路由定义一个全局 404 页面。这在路由级别处理,不依赖于渲染布局或页面。

not-found.js

当路由段内抛出 notFound 函数时,**not-found** 文件用于渲染 UI。除了提供自定义 UI 外,Next.js 会为流式响应返回 200 HTTP 状态码,为非流式响应返回 404

app/not-found.tsx
import Link from 'next/link'
 
export default function NotFound() {
  return (
    <div>
      <h2>Not Found</h2>
      <p>Could not find requested resource</p>
      <Link href="/">Return Home</Link>
    </div>
  )
}

global-not-found.js (实验性)

global-not-found.js 文件允许你为整个应用程序定义一个 404 页面。与在路由级别工作的 not-found.js 不同,当请求的 URL 完全不匹配任何路由时使用此文件。Next.js 会**跳过渲染**并直接返回此全局页面。

global-not-found.js 文件会绕过你的应用程序的正常渲染,这意味着你需要导入 404 页面所需的任何全局样式、字体或其他依赖项。

提示:使用更小版本的全局样式和更简单的字体系列可以提高此页面的性能。

当无法通过 layout.jsnot-found.js 的组合构建 404 页面时,global-not-found.js 会很有用。这可能发生在两种情况下:

  • 你的应用程序有多个根布局(例如 app/(admin)/layout.tsxapp/(shop)/layout.tsx),因此没有单个布局可以构成全局 404。
  • 你的根布局是使用顶级动态段定义的(例如 app/[country]/layout.tsx),这使得构成一致的 404 页面更加困难。

要启用它,请在 next.config.ts 中添加 globalNotFound 标志

next.config.ts
import type { NextConfig } from 'next'
 
const nextConfig: NextConfig = {
  experimental: {
    globalNotFound: true,
  },
}
 
export default nextConfig

然后,在 app 目录的根部创建一个文件:app/global-not-found.js

app/global-not-found.tsx
// Import global styles and fonts
import './globals.css'
import { Inter } from 'next/font/google'
import type { Metadata } from 'next'
 
const inter = Inter({ subsets: ['latin'] })
 
export const metadata: Metadata = {
  title: '404 - Page Not Found',
  description: 'The page you are looking for does not exist.',
}
 
export default function GlobalNotFound() {
  return (
    <html lang="en" className={inter.className}>
      <body>
        <h1>404 - Page Not Found</h1>
        <p>This page does not exist.</p>
      </body>
    </html>
  )
}

not-found.js 不同,此文件必须返回完整的 HTML 文档,包括 <html><body> 标签。

参考

属性

not-found.jsglobal-not-found.js 组件不接受任何属性。

提示:除了捕获预期的 notFound() 错误外,根目录下的 app/not-found.jsapp/global-not-found.js 文件还会处理你整个应用程序中任何不匹配的 URL。这意味着访问你应用程序未处理的 URL 的用户将看到导出的 UI。

示例

数据获取

默认情况下,not-found 是一个服务器组件。你可以将其标记为 async 以获取和显示数据

app/not-found.tsx
import Link from 'next/link'
import { headers } from 'next/headers'
 
export default async function NotFound() {
  const headersList = await headers()
  const domain = headersList.get('host')
  const data = await getSiteData(domain)
  return (
    <div>
      <h2>Not Found: {data.name}</h2>
      <p>Could not find requested resource</p>
      <p>
        View <Link href="/blog">all posts</Link>
      </p>
    </div>
  )
}

如果你需要使用像 usePathname 这样的客户端组件钩子来根据路径显示内容,则必须在客户端获取数据。

元数据

对于 global-not-found.js,你可以导出一个 metadata 对象或一个 generateMetadata 函数来为 404 页面定制 <title><meta> 和其他头部标签

提示:Next.js 会自动为返回 404 状态码的页面(包括 global-not-found.js 页面)注入 <meta name="robots" content="noindex" />

app/global-not-found.tsx
import type { Metadata } from 'next'
 
export const metadata: Metadata = {
  title: 'Not Found',
  description: 'The page you are looking for does not exist.',
}
 
export default function GlobalNotFound() {
  return (
    <html lang="en">
      <body>
        <div>
          <h1>Not Found</h1>
          <p>The page you are looking for does not exist.</p>
        </div>
      </body>
    </html>
  )
}

版本历史

版本更改
v15.4.0global-not-found.js 引入(实验性)。
v13.3.0根目录 app/not-found 处理全局不匹配的 URL。
v13.0.0not-found 引入。