app-router
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseNext.js App Router Patterns
Next.js App Router 路由模式
Overview
概述
The App Router is Next.js's file-system based router built on React Server Components. It uses a directory structure where folders define routes and special files control UI behavior.
app/App Router是Next.js基于React Server Components构建的文件系统路由。它采用目录结构,其中文件夹定义路由,特殊文件控制UI行为。
app/Core File Conventions
核心文件约定
Route Files
路由文件
Each route segment is defined by a folder. Special files within folders control behavior:
| File | Purpose |
|---|---|
| Unique UI for a route, makes route publicly accessible |
| Shared UI wrapper, preserves state across navigations |
| Loading UI using React Suspense |
| Error boundary for route segment |
| UI for 404 responses |
| Like layout but re-renders on navigation |
| Fallback for parallel routes |
每个路由分段由文件夹定义。文件夹内的特殊文件控制行为:
| 文件 | 用途 |
|---|---|
| 为路由提供唯一UI,使路由可公开访问 |
| 共享UI包装器,在导航时保留状态 |
| 使用React Suspense实现的加载UI |
| 路由分段的错误边界 |
| 404响应的UI |
| 类似布局但在导航时重新渲染 |
| 并行路由的回退方案 |
Folder Conventions
文件夹约定
| Pattern | Purpose | Example |
|---|---|---|
| Route segment | |
| Dynamic segment | |
| Catch-all segment | |
| Optional catch-all | |
| Route group (no URL) | |
| Named slot (parallel routes) | |
| Private folder (excluded) | |
| 模式 | 用途 | 示例 |
|---|---|---|
| 路由分段 | |
| 动态分段 | |
| 全捕获分段 | |
| 可选全捕获 | |
| 路由组(不影响URL) | |
| 命名插槽(并行路由) | |
| 私有文件夹(被排除) | |
Creating Routes
创建路由
Basic Route Structure
基础路由结构
To create a new route, add a folder with :
page.tsxapp/
├── page.tsx # / (home)
├── about/
│ └── page.tsx # /about
└── blog/
├── page.tsx # /blog
└── [slug]/
└── page.tsx # /blog/:slug要创建新路由,添加一个包含的文件夹:
page.tsxapp/
├── page.tsx # /(首页)
├── about/
│ └── page.tsx # /about
└── blog/
├── page.tsx # /blog
└── [slug]/
└── page.tsx # /blog/:slugPage Component
页面组件
A page is a Server Component by default:
tsx
// app/about/page.tsx
export default function AboutPage() {
return (
<main>
<h1>About Us</h1>
<p>Welcome to our company.</p>
</main>
)
}页面默认是Server Component:
tsx
// app/about/page.tsx
export default function AboutPage() {
return (
<main>
<h1>关于我们</h1>
<p>欢迎来到我们的公司。</p>
</main>
)
}Dynamic Routes
动态路由
Access route parameters via the prop:
paramstsx
// app/blog/[slug]/page.tsx
interface PageProps {
params: Promise<{ slug: string }>
}
export default async function BlogPost({ params }: PageProps) {
const { slug } = await params
const post = await getPost(slug)
return <article>{post.content}</article>
}通过属性访问路由参数:
paramstsx
// app/blog/[slug]/page.tsx
interface PageProps {
params: Promise<{ slug: string }>
}
export default async function BlogPost({ params }: PageProps) {
const { slug } = await params
const post = await getPost(slug)
return <article>{post.content}</article>
}Layouts
布局
Root Layout (Required)
根布局(必填)
Every app needs a root layout with and :
<html><body>tsx
// app/layout.tsx
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}每个应用都需要包含和的根布局:
<html><body>tsx
// app/layout.tsx
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}Nested Layouts
嵌套布局
Layouts wrap their children and preserve state:
tsx
// app/dashboard/layout.tsx
export default function DashboardLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<div className="flex">
<Sidebar />
<main className="flex-1">{children}</main>
</div>
)
}布局会包裹其子组件并保留状态:
tsx
// app/dashboard/layout.tsx
export default function DashboardLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<div className="flex">
<Sidebar />
<main className="flex-1">{children}</main>
</div>
)
}Loading and Error States
加载与错误状态
Loading UI
加载UI
Create instant loading states with Suspense:
tsx
// app/dashboard/loading.tsx
export default function Loading() {
return <div className="animate-pulse">Loading...</div>
}使用Suspense创建即时加载状态:
tsx
// app/dashboard/loading.tsx
export default function Loading() {
return <div className="animate-pulse">加载中...</div>
}Error Boundaries
错误边界
Handle errors gracefully:
tsx
// app/dashboard/error.tsx
'use client'
export default function Error({
error,
reset,
}: {
error: Error
reset: () => void
}) {
return (
<div>
<h2>Something went wrong!</h2>
<button onClick={reset}>Try again</button>
</div>
)
}优雅处理错误:
tsx
// app/dashboard/error.tsx
'use client'
export default function Error({
error,
reset,
}: {
error: Error
reset: () => void
}) {
return (
<div>
<h2>出问题了!</h2>
<button onClick={reset}>重试</button>
</div>
)
}Route Groups
路由组
Organize routes without affecting URL structure:
app/
├── (marketing)/
│ ├── layout.tsx # Marketing layout
│ ├── about/page.tsx # /about
│ └── contact/page.tsx # /contact
└── (shop)/
├── layout.tsx # Shop layout
└── products/page.tsx # /products在不影响URL结构的情况下整理路由:
app/
├── (marketing)/
│ ├── layout.tsx # 营销布局
│ ├── about/page.tsx # /about
│ └── contact/page.tsx # /contact
└── (shop)/
├── layout.tsx # 商城布局
└── products/page.tsx # /productsMetadata
元数据
Static Metadata
静态元数据
tsx
// app/about/page.tsx
import { Metadata } from 'next'
export const metadata: Metadata = {
title: 'About Us',
description: 'Learn more about our company',
}tsx
// app/about/page.tsx
import { Metadata } from 'next'
export const metadata: Metadata = {
title: 'About Us',
description: 'Learn more about our company',
}Dynamic Metadata
动态元数据
tsx
// app/blog/[slug]/page.tsx
export async function generateMetadata({ params }: PageProps): Promise<Metadata> {
const { slug } = await params
const post = await getPost(slug)
return { title: post.title }
}tsx
// app/blog/[slug]/page.tsx
export async function generateMetadata({ params }: PageProps): Promise<Metadata> {
const { slug } = await params
const post = await getPost(slug)
return { title: post.title }
}Key Patterns
关键模式
- Colocation: Keep components, tests, and styles near routes
- Private folders: Use for non-route files
_folder - Route groups: Use to organize without URL impact
(folder) - Parallel routes: Use for complex layouts
@slot - Intercepting routes: Use patterns for modals
(.)
- 就近放置:将组件、测试和样式放在路由附近
- 私有文件夹:使用存放非路由文件
_folder - 路由组:使用在不影响URL的情况下整理路由
(folder) - 并行路由:使用实现复杂布局
@slot - 拦截路由:使用模式实现模态框
(.)
Resources
资源
For detailed patterns, see:
- - Complete file conventions
references/routing-conventions.md - - Layout composition patterns
references/layouts-templates.md - - Suspense and error handling
references/loading-error-states.md - - Dynamic routing examples
examples/dynamic-routes.md - - Parallel and intercepting routes
examples/parallel-routes.md
如需了解详细模式,请查看:
- - 完整文件约定
references/routing-conventions.md - - 布局组合模式
references/layouts-templates.md - - Suspense与错误处理
references/loading-error-states.md - - 动态路由示例
examples/dynamic-routes.md - - 并行与拦截路由示例
examples/parallel-routes.md