Next.js渲染概述 #
一、渲染策略 #
1.1 渲染类型 #
| 类型 | 缩写 | 说明 |
|---|---|---|
| 静态生成 | SSG | 构建时生成HTML |
| 服务端渲染 | SSR | 请求时生成HTML |
| 增量静态再生 | ISR | 定期更新静态页面 |
| 客户端渲染 | CSR | 浏览器端渲染 |
| React Server Components | RSC | 服务端组件 |
1.2 渲染时机 #
text
构建时 → SSG
请求时 → SSR
定时更新 → ISR
浏览器 → CSR
1.3 选择策略 #
| 场景 | 推荐策略 |
|---|---|
| 静态内容(博客、文档) | SSG |
| 动态内容(用户仪表盘) | SSR |
| 混合内容(电商产品) | ISR |
| 交互丰富(管理后台) | CSR |
二、服务端渲染 vs 客户端渲染 #
2.1 服务端渲染 (SSR) #
text
请求 → 服务器渲染HTML → 返回完整HTML → 浏览器显示
优点:
- SEO友好
- 首屏加载快
- 社交分享支持
缺点:
- 服务器压力大
- TTFB较长
2.2 客户端渲染 (CSR) #
text
请求 → 返回空HTML → 加载JS → 浏览器渲染
优点:
- 服务器压力小
- 交互响应快
- 页面切换流畅
缺点:
- SEO不友好
- 首屏加载慢
- 需要JS支持
2.3 Next.js混合渲染 #
tsx
export default function Page() {
return (
<div>
<ServerComponent />
<ClientComponent />
</div>
)
}
三、React Server Components #
3.1 概念 #
Server Components 是在服务端执行的React组件:
tsx
async function ServerComponent() {
const data = await fetch('https://api.example.com/data')
const result = await data.json()
return <div>{result.title}</div>
}
3.2 Server vs Client Components #
| 特性 | Server Components | Client Components |
|---|---|---|
| 执行位置 | 服务端 | 客户端 |
| 数据获取 | 直接访问 | fetch/API |
| 状态管理 | 不支持 | 支持 |
| 事件处理 | 不支持 | 支持 |
| Hooks | 不支持 | 支持 |
| 浏览器API | 不支持 | 支持 |
3.3 使用场景 #
Server Components
- 数据获取
- 访问后端资源
- 保护敏感信息
- 减少包大小
Client Components
- 交互功能
- 状态管理
- 浏览器API
- 事件处理
3.4 组合使用 #
tsx
import ClientCounter from './ClientCounter'
export default async function Page() {
const data = await getData()
return (
<div>
<h1>{data.title}</h1>
<ClientCounter initialValue={data.count} />
</div>
)
}
四、渲染配置 #
4.1 段配置选项 #
tsx
export const dynamic = 'force-dynamic'
export const dynamicParams = true
export const revalidate = false
export const fetchCache = 'auto'
export const runtime = 'nodejs'
export const preferredRegion = 'auto'
4.2 dynamic选项 #
| 值 | 说明 |
|---|---|
| ‘auto’ | 自动决定(默认) |
| ‘force-dynamic’ | 强制动态渲染 |
| ‘error’ | 静态时报错 |
| ‘force-static’ | 强制静态渲染 |
4.3 revalidate选项 #
tsx
export const revalidate = 3600
| 值 | 说明 |
|---|---|
| false | 永不重新验证 |
| 0 | 每次请求验证 |
| number | 指定秒数后验证 |
4.4 runtime选项 #
| 值 | 说明 |
|---|---|
| ‘nodejs’ | Node.js运行时 |
| ‘edge’ | Edge运行时 |
五、静态渲染 #
5.1 默认行为 #
tsx
export default async function Page() {
const data = await fetch('https://api.example.com/data')
return <div>{data}</div>
}
默认会静态渲染。
5.2 强制静态 #
tsx
export const dynamic = 'force-static'
export default async function Page() {
const data = await fetch('https://api.example.com/data', {
cache: 'force-cache',
})
return <div>{data}</div>
}
5.3 generateStaticParams #
tsx
export async function generateStaticParams() {
const posts = await getPosts()
return posts.map(post => ({
slug: post.slug,
}))
}
export default async function Page({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params
const post = await getPost(slug)
return <article>{post.content}</article>
}
六、动态渲染 #
6.1 动态函数 #
使用动态函数会触发动态渲染:
tsx
import { cookies, headers, searchParams } from 'next/headers'
export default async function Page() {
const cookieStore = await cookies()
const headersList = await headers()
return <div>{cookieStore.get('token')}</div>
}
6.2 强制动态 #
tsx
export const dynamic = 'force-dynamic'
export default async function Page() {
const data = await fetch('https://api.example.com/data', {
cache: 'no-store',
})
return <div>{data}</div>
}
6.3 动态函数列表 #
| 函数 | 说明 |
|---|---|
| cookies() | 读取Cookie |
| headers() | 读取Header |
| searchParams | 读取查询参数 |
| draftMode() | 检查草稿模式 |
七、流式渲染 #
7.1 Suspense #
tsx
import { Suspense } from 'react'
export default function Page() {
return (
<div>
<h1>页面标题</h1>
<Suspense fallback={<Loading />}>
<SlowComponent />
</Suspense>
</div>
)
}
7.2 加载状态 #
tsx
export default function Loading() {
return (
<div className="animate-pulse">
<div className="h-8 bg-gray-200 rounded w-1/2 mb-4"></div>
<div className="h-4 bg-gray-200 rounded w-3/4"></div>
</div>
)
}
7.3 loading.tsx #
text
app/
├── loading.tsx
└── page.tsx
八、最佳实践 #
8.1 默认使用Server Components #
tsx
export default async function Page() {
const data = await getData()
return <div>{data}</div>
}
8.2 按需使用Client Components #
tsx
'use client'
import { useState } from 'react'
export default function Counter() {
const [count, setCount] = useState(0)
return <button onClick={() => setCount(count + 1)}>{count}</button>
}
8.3 合理分割 #
tsx
export default async function Page() {
const data = await getData()
return (
<div>
<StaticHeader data={data.header} />
<Suspense fallback={<Skeleton />}>
<DynamicContent />
</Suspense>
</div>
)
}
九、总结 #
渲染策略要点:
| 策略 | 说明 | 适用场景 |
|---|---|---|
| SSG | 静态生成 | 静态内容 |
| SSR | 服务端渲染 | 动态内容 |
| ISR | 增量静态再生 | 混合内容 |
| CSR | 客户端渲染 | 交互丰富 |
| RSC | 服务端组件 | 数据获取 |
下一步,让我们深入学习服务端渲染!
最后更新:2026-03-28