跳到主要内容

Next.js 路由系统

Next.js 的路由系统不是单纯把文件映射成路径,它还顺带定义了页面层级、布局继承、加载状态和一部分服务端边界。

Pages Router 的基础路由

普通页面

pages/index.tsx -> /
pages/about.tsx -> /about
pages/posts/list.tsx -> /posts/list

动态路由

pages/posts/[id].tsx -> /posts/1

Catch-all 路由

pages/docs/[...slug].tsx

它可以匹配:

  • /docs/a
  • /docs/a/b
  • /docs/a/b/c

Optional Catch-all

pages/docs/[[...slug]].tsx

它连 /docs 本身也能匹配。

App Router 的路由系统

到了 App Router,路由不只是一张 URL 映射表,而是一套“路由段结构”。

页面入口

app/page.tsx -> /
app/about/page.tsx -> /about
app/blog/[slug]/page.tsx -> /blog/hello

动态参数

export default async function BlogPost({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
return <h1>{slug}</h1>;
}

在较新的版本里,paramssearchParams 需要按异步模型理解。

布局为什么会改变路由体验

layout.tsx 是 App Router 最值得重视的能力之一。

app/
layout.tsx
dashboard/
layout.tsx
page.tsx
settings/
page.tsx

这意味着:

  • 根布局包住全站
  • dashboard/layout.tsx 只包住 dashboard 这一路径下的页面
  • 路由切换时,共享布局部分可以被复用,不需要整页重新挂载

这也是 App Router 体验和传统 React Router 不太一样的原因之一。

路由组

app/(marketing)/about/page.tsx
app/(dashboard)/settings/page.tsx

路由组不会进入 URL。它的作用是:

  • 整理目录
  • 区分布局
  • 在不改变地址结构的前提下划分区域

并行路由

app/@team/page.tsx
app/@analytics/page.tsx

并行路由适合多区域同时渲染的页面,例如:

  • 仪表盘
  • 多面板后台
  • 一个主页面带多个内容槽位

它不是高频入门能力,但在大型后台里很常见。

拦截路由

拦截路由常见于:

  • 列表页中打开详情弹层
  • 地址变化,但底层页面保持上下文
  • 模态详情和独立详情页共用同一路由资源

官方给出的文件约定比较特殊,例如 (..)(...) 这类写法,第一次看会有些绕,建议在需要做 modal routing 时再专门深挖。

导航方式

import Link from 'next/link';

export default function Nav() {
return <Link href="/dashboard">Dashboard</Link>;
}

这是默认首选方式。它会接入 Next 的预取和客户端导航能力。

编程式导航

'use client';

import { useRouter } from 'next/navigation';

export default function Actions() {
const router = useRouter();

return <button onClick={() => router.push('/orders')}>Orders</button>;
}

读取当前路径

'use client';

import { usePathname, useSearchParams } from 'next/navigation';

export default function CurrentRoute() {
const pathname = usePathname();
const searchParams = useSearchParams();

return (
<div>
<div>{pathname}</div>
<div>{searchParams.get('q')}</div>
</div>
);
}

Route Handlers

App Router 下,接口层也接进了文件系统路由:

app/api/posts/route.ts
export async function GET() {
return Response.json([{ id: 1, title: 'Hello' }]);
}

这让前端项目在很多轻量 BFF 场景下不需要马上拆独立服务。

路由系统最常见的误区

1. 把 URL 结构和目录结构完全绑定死

Next 的文件系统路由是主线,但路由组、并行路由、拦截路由都在说明:目录结构仍然有“组织层”和“URL 层”的区别。

2. 低估 layout.tsx 的作用

布局复用不只是省代码,它会直接影响页面切换体验和组件重挂载行为。

3. 把 Route Handlers 当成完整后端替代品

做轻量接口可以,做重服务端系统则要谨慎。

推荐继续往下看

  1. 渲染与数据获取
  2. 缓存与重验证
  3. Server Actions

参考资料