Next.js App Router 目录结构详解(基于 App Router 的新范例)
Next.js 13+ 引入的 App Router 是对原有文件系统路由的重大升级,采用了更符合 React 生态的约定。下面我将基于 App Router 重新组织目录结构并给出完整示例。
一、App Router 基础目录结构
my-next-app/ ├── app/ # 新核心路由目录(替代旧版 pages) ├── components/ # 共享组件 ├── lib/ # 业务逻辑 ├── styles/ # 全局样式 ├── public/ # 静态资源 ├── next.config.js ├── tsconfig.json/jsconfig.json └── package.json
二、app/ 目录深度解析(App Router 核心)
1. 基本路由示例
app/ ├── layout.js # 根布局(必需) ├── page.js # 根页面(/) ├── dashboard/ # 嵌套路由 │ ├── page.js # /dashboard │ ├── layout.js # 嵌套布局 │ └── analytics/ # 动态嵌套 │ └── page.js # /dashboard/analytics ├── posts/ │ ├── page.js # /posts 列表页 │ ├── [id]/ # 动态路由 │ │ ├── page.js # /posts/123 │ │ └── loading.js # 加载状态 │ └── create/ │ └── page.js # /posts/create └── error.js # 全局错误处理
2. 关键文件说明
必需文件:
-
layout.js- 每个目录的布局组件(根目录必须存在)// app/layout.js export default function RootLayout({ children }) { return ( <html lang="en"> <body>{children}</body> </html> ); } -
page.js- 路由页面组件(每个路由目录必须有一个)// app/page.js export default function HomePage() { return <h1>Welcome to Next.js!</h1>; }
可选但推荐的文件:
-
loading.js- 路由加载状态(Suspense 边界)// app/posts/[id]/loading.js export default function Loading() { return <div>Loading post...</div>; } -
error.js- 路由级错误处理// app/posts/[id]/error.js 'use client'; export default function Error({ error, reset }) { return ( <div> <h2>Something went wrong!</h2> <button onClick={reset}>Try again</button> </div> ); } -
not-found.js- 404 处理// app/posts/not-found.js export default function NotFound() { return <div>Post not found</div>; }
3. 动态路由示例
app/ ├── products/ │ ├── [category]/ # 动态段 │ │ ├── page.js # /products/electronics │ │ └── [id]/ # 嵌套动态路由 │ │ └── page.js # /products/electronics/123 │ └── loading.js # 共享加载状态
实现代码:
// app/products/[category]/[id]/page.js async function getProduct(category, id) { const res = await fetch(`https://api.example.com/products/${category}/${id}`); return res.json(); } export default async function ProductPage({ params }) { const product = await getProduct(params.category, params.id); return <div>{product.name}</div>; }
三、完整项目结构示例
my-next-app/ ├── app/ │ ├── layout.js # 根布局 │ ├── page.js # 首页 │ ├── dashboard/ # 仪表盘模块 │ │ ├── layout.js # 仪表盘布局 │ │ ├── page.js # 仪表盘首页 │ │ └── settings/ # 设置子路由 │ │ └── page.js # /dashboard/settings │ ├── blog/ # 博客模块 │ │ ├── layout.js # 博客布局 │ │ ├── page.js # 博客列表 │ │ ├── [slug]/ # 动态博客页 │ │ │ └── page.js # /blog/post-slug │ │ └── categories/ # 分类路由 │ │ └── [name]/ # /blog/categories/tech │ │ └── page.js │ ├── api/ # API 路由(新位置) │ │ └── auth/ # 认证相关 │ │ └── route.js # POST /api/auth │ └── error.js # 全局错误处理 ├── components/ │ ├── ui/ # 基础UI组件 │ ├── BlogPostCard.jsx # 博客卡片组件 │ └── Layout/ # 布局组件 │ ├── Header.jsx │ └── Sidebar.jsx ├── lib/ │ ├── api/ # API客户端 │ │ └── blog.js │ ├── auth/ # 认证逻辑 │ └── utils.js # 工具函数 ├── styles/ │ └── globals.css # 全局样式 ├── public/ │ └── images/ └── next.config.js
四、App Router 核心特性实现
1. 并行路由(Parallel Routes)
app/ ├── (marketing)/ # 并行路由组 │ ├── layout.js │ └── page.js └── (dashboard)/ # 另一个并行路由组 ├── layout.js └── page.js
访问 / 时会同时渲染两个路由组的内容。
2. 路由拦截器(Interception Routes)
app/ ├── dashboard/ │ ├── layout.js │ └── page.js └── (auth)/ ├── signin/ │ └── page.js └── layout.js # 拦截器布局
3. 服务器组件与客户端组件
// app/dashboard/page.js - 默认是服务器组件 async function getData() { const res = await fetch('https://api.example.com/data'); return res.json(); } export default async function DashboardPage() { const data = await getData(); return <div>{/* 服务器渲染内容 */}</div>; }
// 需要客户端功能的组件 'use client'; import { useState } from 'react'; export default function Counter() { const [count, setCount] = useState(0); return <button onClick={() => setCount(c => c + 1)}>{count}</button>; }
五、迁移指南(从 Pages Router 到 App Router)
-
路由目录变更:
pages/→app/- API 路由从
pages/api/移到app/api/
-
特殊文件变更:
_app.js→app/layout.js_document.js→ 不再需要(自动处理)pages/404.js→app/not-found.js
-
数据获取方式:
getStaticProps/getServerSideProps→ 使用 React 异步组件或fetchgetStaticPaths→ 使用generateStaticParams(静态导出时)
六、最佳实践
-
路由组织原则:
- 按功能模块组织路由
- 公共布局放在上层目录
- 频繁变化的路由考虑使用客户端导航
-
性能优化:
- 合理使用
loading.js提供即时反馈 - 对静态内容使用静态生成
- 对频繁更新数据使用增量静态再生
- 合理使用
-
错误处理:
- 实现路由级
error.js - 使用
useErrorBoundary钩子(未来版本) - 区分客户端和服务器错误
- 实现路由级
Next.js 的 App Router 代表了框架发展的新方向,通过更紧密的 React 集成和更清晰的约定,使得构建复杂应用变得更加直观。建议新项目直接采用 App Router,现有项目可以逐步迁移。