nextjs-best-practices

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Next.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 child
Does it need...?
├── useState, useEffect, event handlers
│   └── Client Component ('use client')
├── Direct data fetching, no interactivity
│   └── Server Component (default)
└── Both? 
    └── Split: Server parent + Client child

By Default

默认规则

TypeUse
ServerData fetching, layout, static content
ClientForms, buttons, interactive UI

类型适用场景
Server数据获取、布局、静态内容
Client表单、按钮、交互式UI

2. Data Fetching Patterns

2. 数据获取模式

Fetch Strategy

获取策略

PatternUse
DefaultStatic (cached at build)
RevalidateISR (time-based refresh)
No-storeDynamic (every request)
模式适用场景
Default静态(构建时缓存)
RevalidateISR(基于时间的刷新)
No-store动态(每次请求都获取)

Data Flow

数据流

SourcePattern
DatabaseServer Component fetch
APIfetch with caching
User inputClient state + server action

数据源模式
DatabaseServer Component 中获取
API带缓存的fetch请求
User inputClient 状态 + Server Actions

3. Routing Principles

3. 路由原则

File Conventions

文件约定

FilePurpose
page.tsx
Route UI
layout.tsx
Shared layout
loading.tsx
Loading state
error.tsx
Error boundary
not-found.tsx
404 page
文件用途
page.tsx
路由UI
layout.tsx
共享布局
loading.tsx
加载状态
error.tsx
错误边界
not-found.tsx
404页面

Route Organization

路由组织

PatternUse
Route groups
(name)
Organize without URL
Parallel routes
@slot
Multiple same-level pages
Intercepting
(.)
Modal overlays

模式适用场景
Route groups
(name)
分组组织,不影响URL
Parallel routes
@slot
多同级页面
Intercepting
(.)
模态弹窗覆盖

4. API Routes

4. API 路由

Route Handlers

路由处理器

MethodUse
GETRead data
POSTCreate data
PUT/PATCHUpdate data
DELETERemove 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 动态

TypeUse
Static exportFixed metadata
generateMetadataDynamic 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

缓存层级

LayerControl
Requestfetch options
Datarevalidate/tags
Full routeroute config
层级控制方式
Requestfetch选项
Datarevalidate/标签
Full route路由配置

Revalidation

重新验证

MethodUse
Time-based
revalidate: 60
On-demand
revalidatePath/Tag
No cache
no-store

方式适用场景
Time-based
revalidate: 60
On-demand
revalidatePath/Tag
No cache
no-store

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' everywhereServer by default
Fetch in client componentsFetch in server
Skip loading statesUse loading.tsx
Ignore error boundariesUse error.tsx
Large client bundlesDynamic 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组件。