Next.js 面试题详细答案 - Q3
Q3: 解释 Next.js 15 中的渲染模式:SSR、SSG、CSR 以及 ISR(增量静态再生)。它们分别在什么场景下使用?
渲染模式概览
Next.js 15 支持四种主要的渲染模式,每种都有其特定的使用场景和优势。
1. SSR (Server-Side Rendering) - 服务端渲染
工作原理:每次请求时在服务器上渲染页面,然后发送完整的 HTML 到客户端。
// 默认行为 - 每次请求时渲染
async function BlogPost({ params }) {
const post = await fetch(`/api/posts/${params.slug}`, {
cache: 'no-store', // 禁用缓存
})
return (
<article>
<h1>{post.title}</h1>
<p>{post.content}</p>
<time>{new Date().toLocaleString()}</time>
</article>
)
}
使用场景:
- 个性化内容(用户仪表盘)
- 实时数据(股票价格、新闻)
- 需要认证的页面
- 频繁更新的内容
优势:
- 实时数据
- SEO 友好
- 个性化内容
劣势:
- 服务器负载高
- 响应时间较长
2. SSG (Static Site Generation) - 静态站点生成
工作原理:构建时预渲染页面,生成静态 HTML 文件。
// 静态生成
async function BlogList() {
const posts = await fetch('/api/posts', {
cache: 'force-cache', // 强制缓存
})
return (
<ul>
{posts.map((post) => (
<li key={post.id}>
<Link href={`/blog/${post.slug}`}>{post.title}</Link>
</li>
))}
</ul>
)
}
// 动态路由的静态生成
export async function generateStaticParams() {
const posts = await fetch('/api/posts')
return posts.map((post) => ({
slug: post.slug,
}))
}
使用场景:
- 博客文章
- 产品页面
- 文档网站
- 营销页面
优势:
- 极快的加载速度
- 低服务器成本
- 高可用性
- 优秀的 SEO
劣势:
- 构建时间长
- 内容更新需要重新构建
3. CSR (Client-Side Rendering) - 客户端渲染
工作原理:在客户端使用 JavaScript 渲染页面。
'use client'
import { useState, useEffect } from 'react'
function Dashboard() {
const [data, setData] = useState(null)
const [loading, setLoading] = useState(true)
useEffect(() => {
fetch('/api/user-data')
.then((res) => res.json())
.then((data) => {
setData(data)
setLoading(false)
})
}, [])
if (loading) return <div>加载中...</div>
return (
<div>
<h1>用户仪表盘</h1>
<p>欢迎, {data.name}!</p>
</div>
)
}
使用场景:
- 交互式应用
- 用户仪表盘
- 实时聊天
- 游戏应用
优势:
- 丰富的交互性
- 快速导航
- 离线功能
劣势:
- 首屏加载慢
- SEO 不友好
- 需要 JavaScript
4. ISR (Incremental Static Regeneration) - 增量静态再生
工作原理:结合 SSG 和 SSR 的优势,在后台更新静态页面。
// 基础 ISR
async function ProductPage({ params }) {
const product = await fetch(`/api/products/${params.id}`, {
next: { revalidate: 3600 }, // 1小时后重新验证
})
return (
<div>
<h1>{product.name}</h1>
<p>价格: ${product.price}</p>
</div>
)
}
// 按需重新验证
export async function GET(request) {
const { searchParams } = new URL(request.url)
const secret = searchParams.get('secret')
if (secret !== process.env.REVALIDATE_SECRET) {
return Response.json({ message: 'Invalid secret' }, { status: 401 })
}
try {
await revalidatePath('/products')
return Response.json({ revalidated: true })
} catch (err) {
return Response.json({ message: 'Error revalidating' }, { status: 500 })
}
}
使用场景:
- 电商产品页面
- 新闻文章
- 用户生成内容
- 定期更新的内容
优势:
- 静态页面的性能
- 动态内容的灵活性
- 自动更新机制
劣势:
- 首次访问可能较慢
- 缓存失效延迟
渲染模式选择指南
1. 内容类型决定渲染模式
// 静态内容 - SSG
export default function AboutPage() {
return <h1>关于我们</h1>
}
// 动态内容 - SSR
async function UserProfile({ params }) {
const user = await fetch(`/api/users/${params.id}`, {
cache: 'no-store',
})
return <div>{user.name}</div>
}
// 混合内容 - ISR
async function BlogPost({ params }) {
const post = await fetch(`/api/posts/${params.slug}`, {
next: { revalidate: 86400 }, // 24小时
})
return <article>{post.content}</article>
}
2. 性能考虑
// 性能优化策略
const fetchConfig = {
// 静态内容 - 永久缓存
static: { cache: 'force-cache' },
// 动态内容 - 不缓存
dynamic: { cache: 'no-store' },
// 定期更新 - ISR
isr: { next: { revalidate: 3600 } },
// 按需更新 - 标签缓存
tagged: { next: { tags: ['posts'] } },
}
3. 实际应用示例
// 电商网站渲染策略
app / page.js // 首页 - SSG
products /
page.js[id] / // 产品列表 - ISR (1小时)
page.js // 产品详情 - ISR (30分钟)
cart / page.js // 购物车 - CSR
dashboard / page.js // 用户仪表盘 - SSR
最佳实践
- 默认使用 SSG:适合大多数内容
- 个性化内容用 SSR:用户相关数据
- 交互式功能用 CSR:复杂用户界面
- 定期更新用 ISR:平衡性能和新鲜度
总结
选择合适的渲染模式需要考虑:
- 内容更新频率
- 个性化需求
- 性能要求
- SEO 重要性
- 用户体验
Next.js 15 的灵活性允许在同一个应用中混合使用不同的渲染模式,为每种内容选择最合适的策略。