Next.js 系列之的SSG、SSR、ISR、CSR 的详细介绍和区别
Next.js 提供了多种渲染策略(SSG、SSR、ISR、CSR),每种策略适用于不同的场景。以下是它们的核心区别、实现方式及最佳实践:
1. SSG(Static Site Generation,静态生成)
核心特点
- 生成时机:在构建时(
next build)生成静态 HTML。 - 数据获取:通过
getStaticProps获取数据,支持预渲染所有页面。 - 适用场景:内容不经常变化的页面(如博客、文档、营销页)。
- 优点:加载最快、SEO 友好、CDN 缓存友好。
- 缺点:无法实时更新内容,需重新构建才能更新。
实现代码
// pages/blog/[slug].js
export async function getStaticPaths() {
// 预生成所有可能的路径(如博客文章列表)
const posts = await fetch('<https://api.example.com/posts>');
return {
paths: posts.map(post => ({ params: { slug: post.slug } })),
fallback: false, // 未预生成的路径返回 404
};
}
export async function getStaticProps({ params }) {
// 根据 slug 获取单篇文章内容
const post = await fetch(`https://api.example.com/posts/${params.slug}`);
return { props: { post } };
}
export default function BlogPost({ post }) {
return <article>{post.content}</article>;
}
2. SSR(Server-Side Rendering,服务端渲染)
核心特点
- 生成时机:每次页面请求时在服务端动态生成 HTML。
- 数据获取:通过
getServerSideProps在请求时获取最新数据。 - 适用场景:需要实时数据的页面(如用户仪表盘、实时股价)。
- 优点:内容始终最新,支持个性化渲染(如基于 Cookie 的权限验证)。
- 缺点:TTFB(首字节时间)较慢,服务端压力大。
实现代码
// pages/dashboard.js
export async function getServerSideProps(context) {
// 从请求中获取 Cookie 或用户信息
const user = await getUserFromCookie(context.req.cookies);
const data = await fetch(`https://api.example.com/dashboard?user=${user.id}`);
return { props: { data } };
}
export default function Dashboard({ data }) {
return <div>{data.stats}</div>;
}
3. ISR(Incremental Static Regeneration,增量静态再生)
核心特点
- 生成时机:SSG 的扩展,允许在运行时按需重新生成静态页面。
- 数据获取:在
getStaticProps中设置revalidate参数(秒),触发条件: • 初次访问时生成静态页面。 • 后续访问时,若超过revalidate时间,后台重新生成页面。 - 适用场景:内容更新频率适中的页面(如电商产品页、新闻列表)。
- 优点:兼具 SSG 的速度和 SSR 的更新能力,减轻服务端压力。
- 缺点:再生成期间用户可能看到旧数据。
实现代码
// pages/products/[id].js
export async function getStaticPaths() {
return { paths: [], fallback: 'blocking' }; // 动态生成所有路径
}
export async function getStaticProps({ params }) {
const product = await fetch(`https://api.example.com/products/${params.id}`);
return {
props: { product },
revalidate: 3600, // 每 1 小时重新验证一次
};
}
export default function Product({ product }) {
return <div>{product.name}</div>;
}
4. CSR(Client-Side Rendering,客户端渲染)
核心特点
- 生成时机:在客户端浏览器中通过 JavaScript 渲染内容。
- 数据获取:通过
useEffect或SWR在组件挂载后获取数据。 - 适用场景:交互性强、无需 SEO 的页面(如用户后台、管理面板)。
- 优点:减少服务端负载,支持动态交互。
- 缺点:首屏加载慢,SEO 不友好,依赖客户端 JavaScript。
实现代码
// pages/profile.js
import { useEffect, useState } from 'react';
export default function Profile() {
const [user, setUser] = useState(null);
useEffect(() => {
// 组件挂载后获取用户数据
fetch('/api/user')
.then(res => res.json())
.then(data => setUser(data));
}, []);
if (!user) return <div>Loading...</div>;
return <div>{user.name}</div>;
}
5. 对比表格
| 特性 | SSG | SSR | ISR | CSR |
|---|---|---|---|---|
| 生成时机 | 构建时 | 每次请求时 | 构建时 + 按需再生 | 客户端运行时 |
| 数据实时性 | 低(需重新构建) | 高(实时) | 中等(可配置更新间隔) | 高(动态获取) |
| SEO 支持 | ✅ 最佳 | ✅ 良好 | ✅ 良好 | ❌ 差(需额外处理) |
| 首屏加载速度 | ⚡️ 最快 | ⏳ 较慢(依赖服务端) | ⚡️ 快(缓存优先) | ⏳ 慢(需加载 JS) |
| 适用场景 | 静态内容 | 实时数据 | 频繁更新但非实时内容 | 交互复杂、无需 SEO |
| 服务端压力 | 无 | 高 | 低 | 无 |
6. 混合使用策略
Next.js 允许在同一个项目中灵活组合多种渲染方式:
• SSG + CSR:首屏静态渲染,交互部分客户端加载(如博客的评论模块)。
• SSR + ISR:动态页面初次 SSR,后续通过 ISR 缓存(如新闻详情页)。
• App Router 优化:在 app 目录中,使用 React Server Components 减少客户端 JS 体积。
示例:混合 SSG 和 CSR
// pages/index.js(SSG 主页面)
export async function getStaticProps() {
const posts = await fetch('<https://api.example.com/posts>');
return { props: { posts } };
}
export default function Home({ posts }) {
// 主内容静态生成,评论模块客户端渲染
return (
<div>
{posts.map(post => <Post key={post.id} {...post} />)}
<ClientOnly>
<Comments />
</ClientOnly>
</div>
);
}
// 客户端组件(仅在浏览器加载)
function Comments() {
const [comments, setComments] = useState([]);
useEffect(() => {
fetch('/api/comments').then(res => res.json()).then(setComments);
}, []);
return <div>{comments.map(comment => <div>{comment.text}</div>)}</div>;
}
7. 选择策略的决策树
- 是否需要 SEO? • ✅ 是 → 使用 SSG、SSR 或 ISR。 • ❌ 否 → 使用 CSR。
- 数据是否频繁更新? • ✅ 是 → 使用 SSR 或 ISR。 • ❌ 否 → 使用 SSG。
- 是否有个性化内容? • ✅ 是 → 使用 SSR。 • ❌ 否 → 使用 SSG 或 ISR。
总结
- SSG:优先用于内容稳定、SEO 关键的页面。
- SSR:用于实时数据或个性化内容。
- ISR:平衡速度与更新频率,适合大规模内容站点。
- CSR:用于交互复杂、无需 SEO 的功能模块。
- 混合使用:结合不同策略,最大化性能与功能灵活性。
系列文章
Next.js 系列之客户端组件(Client Components)和服务端组件(Server Components)的区别
Next.js 系列之Serverless(无服务器架构)介绍