路由基础
Nextjs13 版本引进了新的功能和约定的 App 路由,新的路由功能可用于 app 文件夹,与 page 文件夹的功能共存。
升级 Nextjs13 并不需要使用新的 App 路由,我们可以在两个文件夹内继续使用新的功能,诸如升级后的 image 组件、Link 组件、Script 组件和字体优化等。
官方术语表
Nextjs13 beta 版的文档介绍先给出一张专业的术语表,因为这些术语贯穿整个文档。

-
Tree:一种可视化的约定结构。比如组件 tree、文件夹结构等
-
Subtree:属于 tree 的一部分,开始于 root (根)结束于 leaves(叶)
-
Root:Subtree 的第一个节点,就像 root layout
-
Leaf:subtree 的最后一个节点,就像 url 的最后一段(segment)

-
URL Segment:URL 的 path 的一部分,以
/为分割界限 -
URL Path:URL 的一部分,在 domain 的后面
app 路由
在第 13 版本,Next.js 引入了一种新的基于React服务端组件的App Router。支持共享 layout、嵌套路由、loading 状态、error 处理等等。
App 路由在 app 文件夹下运行。
默认情况下,在 app 目录下的组件是 React 服务端组件,这是一种性能的优化以及让我们更简单地采用它们。当然,我们还可以使用客户端组件。
文件夹规则
Nextjs 使用基于文件系统的路由:
- 目录用来定义路由。一个路由是嵌套目录的 path,遵循文件系统层次结构,从根文件夹向下到包含 page.js 文件的叶子目录。
- 文件则用来为每个
segment创建 UI 界面。
Route Segment
在路由中每一个目录都代表着route segment,每一个segment都映射着URL path 中的 segment。
举个例子:当我们想要一段/dashboard/settings的路由,在 app 目录下使用两个嵌套的目录可以做到。

/dashboard/settings路由被三个 segment 所组成:
/root segmentdashboard(Segment)settings(Leaf segment)
文件约定
Next.js 提供了一组有专门目的的文件来创建嵌套路由中具有特定行为的 UI:
| layout | 规则 |
|---|---|
| layout | 在多个页面之间共享 UI。在导航时,布局会保留状态、保持交互并且不会重新呈现。 |
| page | 路由的唯一用户界面,访问该段的路由就会访问到 page.js 里的页面组件。 |
| loading | 该路由的主页面在异步渲染中,会显示的 loading 组件的内容。 |
| not-found | 当路由不匹配时,显示的 404 页面。 |
| error | 该路由渲染出错时,会显示该页面。 |
| global-error | 与 error.js 相似,但是专注于捕获根 layout.js 的错误。 |
| route | 为路由创建服务端 API。 |
| template | 跟 layout 功能相似,但是切换路由时,会刷新。 |
| default | 并行路由 Parallel Routes的后备 |
这些专用的文件可以使用.js、.jsx或者.tsx的后缀。
组件层次结构
React 组件在表示 route segment 的专用文件中定义,并且根据特殊的层次结构渲染。
layout.jstemplate.jserror.js(React error boundary)loading.js(React suspense boundary)not-found.js(React error boundary)page.jsor nestedlayout.js
上面的专用文件会组合成这样的结构。

在嵌套路由中,分段路由的组件会被嵌套在父段的组件内:

Colocation
除了专用的文件以外,还可以将其他文件放在app文件夹内,比如测试用例、样式等。
这是因为使用目录来定义路由时,只有通过page.js或者route.js返回出来的内容才是可被公开寻址的。

具有客户端导航的服务器中心路由
不同于使用客户端路由的page路由,App Router 使用服务端路由让服务端组件和服务端上获取的数据对齐。
尽管路由是服务端的,但是可以使用带有 Link 组件的客户端导航,类似于单页应用程序。
这意味着当用户导航到新的路由时,浏览器不会重新加载页面,相反,URL 将被更新,Nextjs 仅会渲染变化的部分。
此外,当用户在应用程序中导航时,路由器将在内存中的客户端缓存中存储 React Server Component 的负载结果。缓存按照路由 segment 拆分,这允许在任何级别的失效,并确保 React 的并发渲染的一致性。这意味着对于某些情况,先前获取的 segment 的缓存可以被重新使用,进一步提高性能。
局部渲染
当在兄弟路由之间导航,比如下面的/dashboard/settings和/dashboard/analytics,Nextjs 将只获取和渲染 layout 和路由中变化的 page 页面。它并不会重新 fetch 或者重新 render 在 segment 上面的任何东西。这就意味着,在路由间可以共享 layout,当用户在同级页面之间导航时,layout 将被保留。

如果没有局部渲染,每个导航都会导致全部页面重新渲染。
仅渲染正在更新的分段可以减少传输的数据量和执行时间,从而提高性能。
高级路由模式
App Router 还提供了一系列的约定来帮助你实现更多的高级路由模式。
- 并行路由:允许你同时在同一个视图中显示两个或者多个页面,这些页面可以独立导航。您可以在具有自己子导航的分割视图中使用它们。
- 拦截路由:允许你拦截一个路由并在另一个路由的上下文中显示它。当保持当前页面的上下文很重要时,您可以使用它们。例如:在编辑一个任务或者在动态信息流中展开照片时查看所有任务。
这些模式允许您构建更丰富、复杂的用户界面,使得曾经小团队和个人开发者来说历史上复杂的功能也变得更加简单。