next路由规则

分类: 编码创建于: 5/31/2025

Next.js 是一个基于 React 的全栈框架,其路由规则主要基于文件系统(File System Based Routing),即通过项目中 pagesapp 目录下的文件和文件夹结构来定义路由。Next.js 的路由规则非常直观,开发者无需手动配置复杂的路由表,只需按照约定组织文件即可。以下是 Next.js 路由规则的详细说明,涵盖了 pages 目录(传统路由)和 app 目录(App Router,Next.js 13 及以上版本引入)两种模式。


1. 传统路由:基于 pages 目录

在 Next.js 12 及之前的版本(以及未启用 App Router 的项目)中,路由基于 pages 目录下的文件结构。规则如下:

基本路由规则

  • 文件映射到路由pages 目录下的每个 .js, .jsx, .ts, 或 .tsx 文件都会映射到一个路由。
    • 例如:pages/index.js 映射到根路径 /
    • 例如:pages/about.js 映射到路径 /about
  • 嵌套路由:通过文件夹创建嵌套路由。
    • 例如:pages/blog/post.js 映射到路径 /blog/post
  • 动态路由:通过在文件名或文件夹名中使用方括号 [param] 定义动态参数。
    • 例如:pages/post/[id].js 映射到 /post/1, /post/abc 等路径,id 可以通过 useRouter 获取。
    • 例如:pages/shop/[category]/[product].js 映射到 /shop/electronics/phone,其中 categoryproduct 是动态参数。
  • 可选的 Catch-All 路由:使用 [...param] 定义可选的动态路由,捕获多个路径段。
    • 例如:pages/docs/[...slug].js 可以匹配 /docs/a, /docs/a/b, /docs/a/b/c 等,slug 是一个数组。
  • 强制 Catch-All 路由:使用 [[...param]] 定义可选的动态路由,包含根路径。
    • 例如:pages/docs/[[...slug]].js 可以匹配 /docs, /docs/a, /docs/a/b 等。

特殊文件

  • _app.js:自定义 App 组件,用于全局布局或状态管理,不映射到具体路由。
  • _document.js:自定义 HTML 文档结构,仅在服务器端渲染时生效,不映射到路由。
  • _error.js:自定义错误页面,用于处理 404 或 500 错误。
  • 404.js:自定义 404 页面。
  • 500.js:自定义 500 页面。

API 路由

  • pages/api 目录下定义后端接口,文件结构映射到 /api/* 路径。
    • 例如:pages/api/hello.js 映射到 /api/hello
    • 支持动态参数,例如:pages/api/post/[id].js 映射到 /api/post/1

中间件和重写规则

  • 使用 next.config.js 或中间件(Next.js 12 引入)可以重写路由规则、实现重定向或国际化支持。

2. 新路由:基于 app 目录(App Router,Next.js 13 及以上)

从 Next.js 13 开始,引入了基于 app 目录的新路由模式(App Router),旨在支持 React Server Components、更好的性能优化和更灵活的布局。规则如下:

基本路由规则

  • 文件夹映射到路由app 目录下的每个文件夹对应一个路由段,文件 page.jspage.tsx 定义该路由的内容。
    • 例如:app/page.js 映射到根路径 /
    • 例如:app/about/page.js 映射到路径 /about
  • 嵌套路由:通过嵌套文件夹定义嵌套路由。
    • 例如:app/blog/post/page.js 映射到 /blog/post
  • 动态路由:使用 [param] 文件夹定义动态参数。
    • 例如:app/post/[id]/page.js 映射到 /post/1, /post/abcid 可通过 params 获取。
  • 可选的 Catch-All 路由:使用 [...param] 文件夹捕获多个路径段。
    • 例如:app/docs/[...slug]/page.js 匹配 /docs/a, /docs/a/b 等。
  • 强制 Catch-All 路由:使用 [[...param]] 文件夹,包含根路径。
    • 例如:app/docs/[[...slug]]/page.js 匹配 /docs, /docs/a 等。

布局系统

  • layout.js:定义布局文件,可以为特定路由或路由组提供共享布局。
    • 例如:app/layout.js 是根布局,包裹所有页面。
    • 例如:app/dashboard/layout.js/dashboard 及其子路由定义布局。
  • 布局可以嵌套,子路由会继承父路由的布局。

其他特殊文件

  • error.js:定义错误边界,处理特定路由的错误。
  • loading.js:定义加载状态 UI,与 Suspense 结合使用。
  • not-found.js:自定义 404 页面。
  • route.js:定义 API 路由,类似 pages/api,但支持更多 HTTP 方法。

路由组(Route Groups)

  • 使用 (group-name) 形式的文件夹定义路由组,用于组织代码或应用不同布局,不影响 URL 路径。
    • 例如:app/(marketing)/about/page.jsapp/(marketing)/contact/page.js 共享一个布局,但 URL 仍然是 /about/contact

并行路由(Parallel Routes)

  • 使用 @folder 语法定义并行路由,用于在同一页面渲染多个独立的内容。
    • 例如:app/dashboard/@analytics/page.jsapp/dashboard/@overview/page.js 可以在 /dashboard 页面同时渲染。

中间件和配置

  • App Router 支持更强大的中间件,可以用于重定向、URL 重写、身份验证等。
  • 通过 next.config.jsmiddleware.js 配置。

Server Components 和 Client Components

  • 默认情况下,App Router 中的组件是 Server Components(在服务器端渲染)。
  • 使用 "use client" 指令将组件标记为 Client Components(在客户端渲染),支持交互性。

3. 路由优先级

pagesapp 目录中,Next.js 按照以下优先级解析路由:

  1. 静态路由优先于动态路由。
    • 例如:/about 会优先匹配 pages/about.js,而不是 pages/[slug].js
  2. 具体路径优先于 Catch-All 路由。
    • 例如:/docs/a 会优先匹配 pages/docs/a.js,而不是 pages/docs/[...slug].js

4. 获取路由参数和查询参数

  • pages 目录中
    • 使用 useRouter Hook(来自 next/router)获取动态参数和查询参数。
      1import { useRouter } from 'next/router';
      2
      3export default function Post() {
      4  const router = useRouter();
      5  const { id } = router.query; // 获取动态参数
      6  return <div>Post ID: {id}</div>;
      7}
  • app 目录中
    • 动态参数通过 params 传递给页面组件,查询参数通过 searchParams 获取。
      1export default function Post({ params, searchParams }) {
      2  const { id } = params; // 获取动态参数
      3  const query = searchParams.q; // 获取查询参数 ?q=xxx
      4  return <div>Post ID: {id}, Query: {query}</div>;
      5}

5. 路由跳转

  • 客户端导航:使用 next/link 组件或 useRouterpush 方法。
    1import Link from 'next/link';
    2
    3<Link href="/about">About Us</Link>;
    1import { useRouter } from 'next/router'; // 或 next/navigation(App Router)
    2
    3const router = useRouter();
    4router.push('/about');
  • 服务器端重定向:使用 getServerSidePropsgetStaticProps 返回 redirect
    1export async function getServerSideProps(context) {
    2  return {
    3    redirect: {
    4      destination: '/about',
    5      permanent: false,
    6    },
    7  };
    8}

6. 国际化路由

Next.js 支持国际化路由,通过 next.config.js 配置 i18n 实现多语言支持。

1module.exports = {
2  i18n: {
3    locales: ['en', 'zh'],
4    defaultLocale: 'en',
5  },
6};
  • 路由会自动添加语言前缀,例如 /en/about/zh/about

总结

  • Pages Routerpages 目录):传统路由,基于文件系统,简单易用,适合小型项目或需要快速开发的场景。
  • App Routerapp 目录):Next.js 13+ 引入,支持 Server Components、布局系统和更复杂的功能,适合现代大型应用。
  • 路由规则的核心是文件系统约定,开发者通过文件和文件夹的命名来定义静态、动态和嵌套路由。

如果你有具体的路由问题或需要某个功能的代码示例,请告诉我,我会进一步帮助你!