项目结构与核心文件
一个标准的 Next.js App Router 项目,其核心在于 /app 目录。
-
/app: 应用的核心,所有的路由和页面 UI 都在这里定义。
-
app/layout.tsx: 根布局。这是个必须文件,它包裹了应用的所有页面。-
默认是服务端组件 (Server Component)。
-
用途:定义全局共享的 UI(如页头、页脚)、引入全局 CSS 文件、放置 Context Provider 等。
-
示例(来自本项目):
// src/app/layout.tsx export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <html lang="en"> <body> <ThemeProvider> {/* 全局 Provider 就在这里放置 */} <Header /> <main>{children}</main> </ThemeProvider> </body> </html> ); }
-
-
app/page.tsx: 页面文件。一个文件夹下的page.tsx文件定义了这个路由下可以被公开访问的 UI。例如,app/page.tsx就是网站的根路径/的页面。 -
/public: 静态资源目录。放置图片、字体、
favicon.ico等文件。这里的文件会从根 URL (/) 开始提供服务。例如,public/avatar.jpg可以通过http://localhost:3000/avatar.jpg访问。 -
next.config.ts: Next.js 配置文件。用于配置高级功能,例如 MDX 集成、重定向、环境变量等。
App Router 的路由机制
核心:基于文件系统的路由。目录结构直接映射为 URL 路径。
-
静态路由:
app/page.tsx->/app/dashboard/page.tsx->/dashboardapp/dashboard/settings/page.tsx->/dashboard/settings
-
动态路由: 使用方括号
[]来创建动态路由段。这是构建博客、电商详情页等功能的基础。示例:
app/blog/[slug]/page.tsx这个文件可以匹配/blog/react-hooks、/blog/nextjs-intro等任意路径。路径中的动态部分(react-hooks)会作为params属性传递给页面组件。// 在 app/blog/[slug]/page.tsx // Next.js 会自动将 URL 中的动态段作为 params 传入 export default function BlogPostPage({ params }: { params: { slug: string } }) { // 如果当前 URL 是 /blog/hello-world // 那么 params 的值就是 { slug: 'hello-world' } const { slug } = params; return ( <div> <h1>文章标题:{slug}</h1> {/* 在这里可以根据 slug 去获取对应的文章数据 */} </div> ); }
布局与嵌套路由
-
问题场景: 假设有一个后台管理系统,所有
/dashboard下的页面(如/dashboard/analytics,/dashboard/users)都需要共享一个侧边栏导航,但其他页面(如首页)不需要这个侧边栏。 -
解决方案: 在需要共享布局的目录中创建
layout.tsx文件。示例:创建 Dashboard 布局
-
创建目录
app/dashboard/。 -
在该目录中创建
layout.tsx。// app/dashboard/layout.tsx export default function DashboardLayout({ children }: { children: React.ReactNode }) { return ( <section className="flex"> <nav className="w-64 bg-gray-100 p-4"> {/* 这里是 Dashboard 独有的侧边栏 */} <ul> <li>Analytics</li> <li>Users</li> </ul> </nav> {/* children 会是 dashboard/page.tsx 或 dashboard/settings/page.tsx 等 */} <main className="flex-1 p-4">{children}</main> </section> ); } -
创建
dashboard的页面。app/dashboard/page.tsx->/dashboard页面app/dashboard/settings/page.tsx->/dashboard/settings页面
现在,访问
/dashboard或/dashboard/settings都会自动被DashboardLayout包裹,拥有统一的侧边栏。而访问/则不会。 -
特殊文件约定与路由组
App Router 提供了一些特殊文件和目录约定,来简化开发。
-
loading.tsx:即时加载状态 这是一个非常有用的文件。只要在某个目录下创建了loading.tsx,Next.js 就会自动用它的内容作为该路由下所有页面的即时加载 UI。它底层利用了React.Suspense。示例:
// app/blog/loading.tsx export default function BlogLoading() { // 这是一个简单的骨架屏 return <div>Loading skeleton for blog...</div>; }现在,当用户访问
/blog或任何/blog/[slug]页面时,如果页面数据还在服务端获取,浏览器会立即显示BlogLoading的内容,而不会白屏,极大地提升了用户体验。 -
error.tsx:错误边界 用于捕获和处理当前路由段的错误。当页面或其子组件在渲染时抛出错误,Next.js 会渲染这个error.tsx文件作为兜底 UI。 注意:error.tsx必须是一个客户端组件 ('use client')。 -
路由组
(...):组织路由而不影响 URL- 问题场景: 想把一组路由(比如所有和市场营销相关的页面
(marketing)/about、(marketing)/contact)放在一个文件夹里来组织代码,但又不希望(marketing)出现在最终的 URL 里。 - 解决方案: 将文件夹名用圆括号包裹起来。
app/(marketing)/about/page.tsx对应的 URL 依然是/about。这个技巧纯粹是为了项目结构管理,对 URL 无任何影响。
- 问题场景: 想把一组路由(比如所有和市场营销相关的页面