nextjs-best-practices
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseNext.js Best Practices
Next.js 最佳实践
Principles for Next.js App Router development.
Next.js App Router 开发原则。
1. Server vs Client Components
1. Server 组件 vs Client 组件
Decision Tree
决策树
Does it need...?
│
├── useState, useEffect, event handlers
│ └── Client Component ('use client')
│
├── Direct data fetching, no interactivity
│ └── Server Component (default)
│
└── Both?
└── Split: Server parent + Client childDoes it need...?
│
├── useState, useEffect, event handlers
│ └── Client Component ('use client')
│
├── Direct data fetching, no interactivity
│ └── Server Component (default)
│
└── Both?
└── Split: Server parent + Client childBy Default
默认规则
| Type | Use |
|---|---|
| Server | Data fetching, layout, static content |
| Client | Forms, buttons, interactive UI |
| 类型 | 适用场景 |
|---|---|
| Server | 数据获取、布局、静态内容 |
| Client | 表单、按钮、交互式UI |
2. Data Fetching Patterns
2. 数据获取模式
Fetch Strategy
获取策略
| Pattern | Use |
|---|---|
| Default | Static (cached at build) |
| Revalidate | ISR (time-based refresh) |
| No-store | Dynamic (every request) |
| 模式 | 适用场景 |
|---|---|
| Default | 静态(构建时缓存) |
| Revalidate | ISR(基于时间的刷新) |
| No-store | 动态(每次请求都获取) |
Data Flow
数据流
| Source | Pattern |
|---|---|
| Database | Server Component fetch |
| API | fetch with caching |
| User input | Client state + server action |
| 数据源 | 模式 |
|---|---|
| Database | Server Component 中获取 |
| API | 带缓存的fetch请求 |
| User input | Client 状态 + Server Actions |
3. Routing Principles
3. 路由原则
File Conventions
文件约定
| File | Purpose |
|---|---|
| Route UI |
| Shared layout |
| Loading state |
| Error boundary |
| 404 page |
| 文件 | 用途 |
|---|---|
| 路由UI |
| 共享布局 |
| 加载状态 |
| 错误边界 |
| 404页面 |
Route Organization
路由组织
| Pattern | Use |
|---|---|
Route groups | Organize without URL |
Parallel routes | Multiple same-level pages |
Intercepting | Modal overlays |
| 模式 | 适用场景 |
|---|---|
Route groups | 分组组织,不影响URL |
Parallel routes | 多同级页面 |
Intercepting | 模态弹窗覆盖 |
4. API Routes
4. API 路由
Route Handlers
路由处理器
| Method | Use |
|---|---|
| GET | Read data |
| POST | Create data |
| PUT/PATCH | Update data |
| DELETE | Remove data |
| 方法 | 用途 |
|---|---|
| GET | 读取数据 |
| POST | 创建数据 |
| PUT/PATCH | 更新数据 |
| DELETE | 删除数据 |
Best Practices
最佳实践
- Validate input with Zod
- Return proper status codes
- Handle errors gracefully
- Use Edge runtime when possible
- 使用Zod验证输入
- 返回正确的状态码
- 优雅处理错误
- 尽可能使用Edge runtime
5. Performance Principles
5. 性能优化原则
Image Optimization
图片优化
- Use next/image component
- Set priority for above-fold
- Provide blur placeholder
- Use responsive sizes
- 使用next/image组件
- 为首屏图片设置priority
- 提供模糊占位图
- 使用响应式尺寸
Bundle Optimization
包体积优化
- Dynamic imports for heavy components
- Route-based code splitting (automatic)
- Analyze with bundle analyzer
- 对大型组件使用动态导入
- 基于路由的代码分割(自动完成)
- 使用包分析工具进行分析
6. Metadata
6. 元数据
Static vs Dynamic
静态 vs 动态
| Type | Use |
|---|---|
| Static export | Fixed metadata |
| generateMetadata | Dynamic per-route |
| 类型 | 适用场景 |
|---|---|
| Static export | 固定元数据 |
| generateMetadata | 基于路由的动态元数据 |
Essential Tags
核心标签
- title (50-60 chars)
- description (150-160 chars)
- Open Graph images
- Canonical URL
- title(50-60字符)
- description(150-160字符)
- Open Graph 图片
- Canonical URL
7. Caching Strategy
7. 缓存策略
Cache Layers
缓存层级
| Layer | Control |
|---|---|
| Request | fetch options |
| Data | revalidate/tags |
| Full route | route config |
| 层级 | 控制方式 |
|---|---|
| Request | fetch选项 |
| Data | revalidate/标签 |
| Full route | 路由配置 |
Revalidation
重新验证
| Method | Use |
|---|---|
| Time-based | |
| On-demand | |
| No cache | |
| 方式 | 适用场景 |
|---|---|
| Time-based | |
| On-demand | |
| No cache | |
8. Server Actions
8. Server Actions
Use Cases
适用场景
- Form submissions
- Data mutations
- Revalidation triggers
- 表单提交
- 数据变更
- 重新验证触发
Best Practices
最佳实践
- Mark with 'use server'
- Validate all inputs
- Return typed responses
- Handle errors
- 标记'use server'
- 验证所有输入
- 返回类型化响应
- 处理错误
9. Anti-Patterns
9. 反模式
| ❌ Don't | ✅ Do |
|---|---|
| 'use client' everywhere | Server by default |
| Fetch in client components | Fetch in server |
| Skip loading states | Use loading.tsx |
| Ignore error boundaries | Use error.tsx |
| Large client bundles | Dynamic imports |
| ❌ 不要做 | ✅ 应该做 |
|---|---|
| 到处使用'use client' | 默认使用Server组件 |
| 在Client组件中获取数据 | 在Server组件中获取数据 |
| 跳过加载状态 | 使用loading.tsx |
| 忽略错误边界 | 使用error.tsx |
| 大型Client包 | 使用动态导入 |
10. Project Structure
10. 项目结构
app/
├── (marketing)/ # Route group
│ └── page.tsx
├── (dashboard)/
│ ├── layout.tsx # Dashboard layout
│ └── page.tsx
├── api/
│ └── [resource]/
│ └── route.ts
└── components/
└── ui/Remember: Server Components are the default for a reason. Start there, add client only when needed.
app/
├── (marketing)/ # Route group
│ └── page.tsx
├── (dashboard)/
│ ├── layout.tsx # Dashboard layout
│ └── page.tsx
├── api/
│ └── [resource]/
│ └── route.ts
└── components/
└── ui/提示: Server Components 被设为默认是有原因的。从Server组件开始,仅在需要时添加Client组件。