Menu

Project structure and organization

本页面概述了 Next.js 中所有的文件夹和文件约定,以及组织项目的建议。

文件夹和文件约定

顶层文件夹

顶层文件夹用于组织应用程序的代码和静态资源。

Route segments to path segments
appApp Router
pagesPages Router
public要提供的静态资源
src可选的应用程序源文件夹

顶层文件

顶层文件用于配置应用程序、管理依赖项、运行代理、集成监控工具和定义环境变量。

Next.js
next.config.jsNext.js 配置文件
package.json项目依赖项和脚本
instrumentation.tsOpenTelemetry 和 Instrumentation 文件
proxy.tsNext.js 请求代理
.env环境变量
.env.local本地环境变量
.env.production生产环境变量
.env.development开发环境变量
eslint.config.mjsESLint 配置文件
.gitignore要忽略的 Git 文件和文件夹
next-env.d.tsNext.js 的 TypeScript 声明文件
tsconfig.jsonTypeScript 配置文件
jsconfig.jsonJavaScript 配置文件

路由文件

添加 page 来暴露路由,layout 用于共享 UI(如 header、nav 或 footer),loading 用于骨架屏,error 用于错误边界,route 用于 API。

layout.js .jsx .tsx布局
page.js .jsx .tsx页面
loading.js .jsx .tsx加载 UI
not-found.js .jsx .tsx未找到 UI
error.js .jsx .tsx错误 UI
global-error.js .jsx .tsx全局错误 UI
route.js .tsAPI 端点
template.js .jsx .tsx重新渲染的布局
default.js .jsx .tsx并行路由回退页面

嵌套路由

文件夹定义 URL 段。嵌套文件夹会嵌套段。任何级别的布局都会包裹其子段。当存在 pageroute 文件时,路由会变为公开的。

路径URL 模式说明
app/layout.tsx根布局包裹所有路由
app/blog/layout.tsx包裹 /blog 及其后代
app/page.tsx/公开路由
app/blog/page.tsx/blog公开路由
app/blog/authors/page.tsx/blog/authors公开路由

动态路由

使用方括号对段进行参数化。使用 [segment] 表示单个参数,[...segment] 表示捕获所有,[[...segment]] 表示可选的捕获所有。通过 params prop 访问值。

路径URL 模式
app/blog/[slug]/page.tsx/blog/my-first-post
app/shop/[...slug]/page.tsx/shop/clothing/shop/clothing/shirts
app/docs/[[...slug]]/page.tsx/docs/docs/layouts-and-pages/docs/api-reference/use-router

路由组和私有文件夹

使用路由组 (group) 组织代码而不改变 URL,使用私有文件夹 _folder 放置不可路由的文件。

路径URL 模式说明
app/(marketing)/page.tsx/组在 URL 中被省略
app/(shop)/cart/page.tsx/cart(shop) 内共享布局
app/blog/_components/Post.tsx不可路由;UI 工具的安全位置
app/blog/_lib/data.ts不可路由;实用工具的安全位置

并行路由和拦截路由

这些功能适用于特定的 UI 模式,例如基于插槽的布局或模态路由。

使用 @slot 表示由父布局渲染的命名插槽。使用拦截模式在当前布局内渲染另一个路由而不改变 URL,例如,在列表上以模态框显示详情视图。

模式(文档)含义典型用例
@folder命名插槽侧边栏 + 主内容
(.)folder拦截同级在模态框中预览同级路由
(..)folder拦截父级将父级的子级作为覆盖层打开
(..)(..)folder拦截两级深度嵌套的覆盖层
(...)folder从根拦截在当前视图中显示任意路由

元数据文件约定

应用图标

favicon.icoFavicon 文件
icon.ico .jpg .jpeg .png .svg应用图标文件
icon.js .ts .tsx生成的应用图标
apple-icon.jpg .jpeg, .pngApple 应用图标文件
apple-icon.js .ts .tsx生成的 Apple 应用图标

Open Graph 和 Twitter 图片

opengraph-image.jpg .jpeg .png .gifOpen Graph 图片文件
opengraph-image.js .ts .tsx生成的 Open Graph 图片
twitter-image.jpg .jpeg .png .gifTwitter 图片文件
twitter-image.js .ts .tsx生成的 Twitter 图片

SEO

sitemap.xml站点地图文件
sitemap.js .ts生成的站点地图
robots.txtRobots 文件
robots.js .ts生成的 Robots 文件

组织你的项目

Next.js 对如何组织和放置项目文件不持意见。但它确实提供了几个功能来帮助你组织项目。

组件层次结构

特殊文件中定义的组件按特定层次结构渲染:

  • layout.js
  • template.js
  • error.js(React 错误边界)
  • loading.js(React suspense 边界)
  • not-found.js("未找到" UI 的 React 错误边界)
  • page.js 或嵌套的 layout.js
Component Hierarchy for File Conventions

在嵌套路由中,组件会递归渲染,这意味着路由段的组件将嵌套在其父段的组件内部

Nested File Conventions Component Hierarchy

文件放置

app 目录中,嵌套文件夹定义路由结构。每个文件夹代表一个路由段,该段映射到 URL 路径中的相应段。

然而,即使通过文件夹定义了路由结构,在将 page.jsroute.js 文件添加到路由段之前,该路由不会公开访问

A diagram showing how a route is not publicly accessible until a page.js or route.js file is added to a route segment.

而且,即使路由被公开访问,也只有 page.jsroute.js 返回的内容会发送到客户端。

A diagram showing how page.js and route.js files make routes publicly accessible.

这意味着项目文件可以安全地放置app 目录的路由段内,而不会意外地变为可路由。

A diagram showing colocated project files are not routable even when a segment contains a page.js or route.js file.

值得注意的是:虽然你可以将项目文件放置在 app 中,但你不必须这样做。如果你愿意,可以将它们保留在 app 目录之外

私有文件夹

可以通过在文件夹前加下划线来创建私有文件夹:_folderName

这表示该文件夹是私有实现细节,路由系统不应考虑它,从而使该文件夹及其所有子文件夹退出路由。

An example folder structure using private folders

由于 app 目录中的文件可以默认安全地放置,因此文件放置不需要私有文件夹。但是,它们可用于:

  • 将 UI 逻辑与路由逻辑分离。
  • 在项目和 Next.js 生态系统中一致地组织内部文件。
  • 在代码编辑器中对文件进行排序和分组。
  • 避免与未来的 Next.js 文件约定产生潜在的命名冲突。

值得注意的是

  • 虽然不是框架约定,但你也可以考虑使用相同的下划线模式将私有文件夹外的文件标记为"私有"。
  • 你可以通过在文件夹名称前加上 %5F(下划线的 URL 编码形式)来创建以下划线开头的 URL 段:%5FfolderName
  • 如果你不使用私有文件夹,了解 Next.js 特殊文件约定会有所帮助,以防止意外的命名冲突。

路由组

可以通过用括号包裹文件夹来创建路由组:(folderName)

这表示该文件夹用于组织目的,不应包含在路由的 URL 路径中。

An example folder structure using route groups

路由组对以下情况很有用:

src 文件夹

Next.js 支持将应用程序代码(包括 app)存储在可选的 src 文件夹中。这将应用程序代码与主要位于项目根目录的项目配置文件分离。

An example folder structure with the `src` folder

示例

以下部分列出了常见策略的高级概述。最简单的要点是选择一个适合你和你的团队的策略,并在整个项目中保持一致。

值得注意的是:在下面的示例中,我们使用 componentslib 文件夹作为通用占位符,它们的命名没有特殊的框架意义,你的项目可能使用其他文件夹,如 uiutilshooksstyles 等。

将项目文件存储在 app 之外

此策略将所有应用程序代码存储在项目根目录的共享文件夹中,并将 app 目录纯粹用于路由目的。

An example folder structure with project files outside of app

将项目文件存储在 app 内的顶层文件夹中

此策略将所有应用程序代码存储在 app 目录根目录的共享文件夹中。

An example folder structure with project files inside app

按功能或路由拆分项目文件

此策略将全局共享的应用程序代码存储在根 app 目录中,并将更具体的应用程序代码拆分到使用它们的路由段中。

An example folder structure with project files split by feature or route

组织路由而不影响 URL 路径

要在不影响 URL 的情况下组织路由,请创建一个组以将相关路由保持在一起。括号中的文件夹将从 URL 中省略(例如 (marketing)(shop))。

Organizing Routes with Route Groups

即使 (marketing)(shop) 内的路由共享相同的 URL 层次结构,你也可以通过在它们的文件夹内添加 layout.js 文件来为每个组创建不同的布局。

Route Groups with Multiple Layouts

将特定段选择加入布局

要将特定路由选择加入布局,请创建一个新的路由组(例如 (shop)),并将共享相同布局的路由移动到该组中(例如 accountcart)。组外的路由将不会共享该布局(例如 checkout)。

Route Groups with Opt-in Layouts

在特定路由上选择加入加载骨架屏

要通过 loading.js 文件将加载骨架屏应用于特定路由,请创建一个新的路由组(例如 /(overview)),然后将你的 loading.tsx 移动到该路由组内。

Folder structure showing a loading.tsx and a page.tsx inside the route group

现在,loading.tsx 文件将仅应用于你的 dashboard → overview 页面,而不是所有 dashboard 页面,而不会影响 URL 路径结构。

创建多个根布局

要创建多个根布局,请删除顶层的 layout.js 文件,并在每个路由组内添加一个 layout.js 文件。这对于将应用程序划分为具有完全不同 UI 或体验的部分很有用。需要将 <html><body> 标签添加到每个根布局。

Route Groups with Multiple Root Layouts

在上面的示例中,(marketing)(shop) 都有自己的根布局。