Project structure and organization
本页面概述了 Next.js 中所有的文件夹和文件约定,以及组织项目的建议。
文件夹和文件约定
顶层文件夹
顶层文件夹用于组织应用程序的代码和静态资源。
顶层文件
顶层文件用于配置应用程序、管理依赖项、运行代理、集成监控工具和定义环境变量。
| Next.js | |
next.config.js | Next.js 配置文件 |
package.json | 项目依赖项和脚本 |
instrumentation.ts | OpenTelemetry 和 Instrumentation 文件 |
proxy.ts | Next.js 请求代理 |
.env | 环境变量 |
.env.local | 本地环境变量 |
.env.production | 生产环境变量 |
.env.development | 开发环境变量 |
eslint.config.mjs | ESLint 配置文件 |
.gitignore | 要忽略的 Git 文件和文件夹 |
next-env.d.ts | Next.js 的 TypeScript 声明文件 |
tsconfig.json | TypeScript 配置文件 |
jsconfig.json | JavaScript 配置文件 |
路由文件
添加 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 .ts | API 端点 |
template | .js .jsx .tsx | 重新渲染的布局 |
default | .js .jsx .tsx | 并行路由回退页面 |
嵌套路由
文件夹定义 URL 段。嵌套文件夹会嵌套段。任何级别的布局都会包裹其子段。当存在 page 或 route 文件时,路由会变为公开的。
| 路径 | 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 | .ico | Favicon 文件 |
icon | .ico .jpg .jpeg .png .svg | 应用图标文件 |
icon | .js .ts .tsx | 生成的应用图标 |
apple-icon | .jpg .jpeg, .png | Apple 应用图标文件 |
apple-icon | .js .ts .tsx | 生成的 Apple 应用图标 |
Open Graph 和 Twitter 图片
opengraph-image | .jpg .jpeg .png .gif | Open Graph 图片文件 |
opengraph-image | .js .ts .tsx | 生成的 Open Graph 图片 |
twitter-image | .jpg .jpeg .png .gif | Twitter 图片文件 |
twitter-image | .js .ts .tsx | 生成的 Twitter 图片 |
SEO
组织你的项目
Next.js 对如何组织和放置项目文件不持意见。但它确实提供了几个功能来帮助你组织项目。
组件层次结构
特殊文件中定义的组件按特定层次结构渲染:
layout.jstemplate.jserror.js(React 错误边界)loading.js(React suspense 边界)not-found.js("未找到" UI 的 React 错误边界)page.js或嵌套的layout.js
在嵌套路由中,组件会递归渲染,这意味着路由段的组件将嵌套在其父段的组件内部。
文件放置
在 app 目录中,嵌套文件夹定义路由结构。每个文件夹代表一个路由段,该段映射到 URL 路径中的相应段。
然而,即使通过文件夹定义了路由结构,在将 page.js 或 route.js 文件添加到路由段之前,该路由不会公开访问。
而且,即使路由被公开访问,也只有 page.js 或 route.js 返回的内容会发送到客户端。
这意味着项目文件可以安全地放置在 app 目录的路由段内,而不会意外地变为可路由。
值得注意的是:虽然你可以将项目文件放置在
app中,但你不必须这样做。如果你愿意,可以将它们保留在app目录之外。
私有文件夹
可以通过在文件夹前加下划线来创建私有文件夹:_folderName
这表示该文件夹是私有实现细节,路由系统不应考虑它,从而使该文件夹及其所有子文件夹退出路由。
由于 app 目录中的文件可以默认安全地放置,因此文件放置不需要私有文件夹。但是,它们可用于:
- 将 UI 逻辑与路由逻辑分离。
- 在项目和 Next.js 生态系统中一致地组织内部文件。
- 在代码编辑器中对文件进行排序和分组。
- 避免与未来的 Next.js 文件约定产生潜在的命名冲突。
值得注意的是:
- 虽然不是框架约定,但你也可以考虑使用相同的下划线模式将私有文件夹外的文件标记为"私有"。
- 你可以通过在文件夹名称前加上
%5F(下划线的 URL 编码形式)来创建以下划线开头的 URL 段:%5FfolderName。- 如果你不使用私有文件夹,了解 Next.js 特殊文件约定会有所帮助,以防止意外的命名冲突。
路由组
可以通过用括号包裹文件夹来创建路由组:(folderName)
这表示该文件夹用于组织目的,不应包含在路由的 URL 路径中。
路由组对以下情况很有用:
- 按站点部分、意图或团队组织路由。例如,营销页面、管理页面等。
- 在同一路由段级别启用嵌套布局:
src 文件夹
Next.js 支持将应用程序代码(包括 app)存储在可选的 src 文件夹中。这将应用程序代码与主要位于项目根目录的项目配置文件分离。
示例
以下部分列出了常见策略的高级概述。最简单的要点是选择一个适合你和你的团队的策略,并在整个项目中保持一致。
值得注意的是:在下面的示例中,我们使用
components和lib文件夹作为通用占位符,它们的命名没有特殊的框架意义,你的项目可能使用其他文件夹,如ui、utils、hooks、styles等。
将项目文件存储在 app 之外
此策略将所有应用程序代码存储在项目根目录的共享文件夹中,并将 app 目录纯粹用于路由目的。
将项目文件存储在 app 内的顶层文件夹中
此策略将所有应用程序代码存储在 app 目录根目录的共享文件夹中。
按功能或路由拆分项目文件
此策略将全局共享的应用程序代码存储在根 app 目录中,并将更具体的应用程序代码拆分到使用它们的路由段中。
组织路由而不影响 URL 路径
要在不影响 URL 的情况下组织路由,请创建一个组以将相关路由保持在一起。括号中的文件夹将从 URL 中省略(例如 (marketing) 或 (shop))。
即使 (marketing) 和 (shop) 内的路由共享相同的 URL 层次结构,你也可以通过在它们的文件夹内添加 layout.js 文件来为每个组创建不同的布局。
将特定段选择加入布局
要将特定路由选择加入布局,请创建一个新的路由组(例如 (shop)),并将共享相同布局的路由移动到该组中(例如 account 和 cart)。组外的路由将不会共享该布局(例如 checkout)。
在特定路由上选择加入加载骨架屏
要通过 loading.js 文件将加载骨架屏应用于特定路由,请创建一个新的路由组(例如 /(overview)),然后将你的 loading.tsx 移动到该路由组内。
现在,loading.tsx 文件将仅应用于你的 dashboard → overview 页面,而不是所有 dashboard 页面,而不会影响 URL 路径结构。
创建多个根布局
要创建多个根布局,请删除顶层的 layout.js 文件,并在每个路由组内添加一个 layout.js 文件。这对于将应用程序划分为具有完全不同 UI 或体验的部分很有用。需要将 <html> 和 <body> 标签添加到每个根布局。
在上面的示例中,(marketing) 和 (shop) 都有自己的根布局。