🧩 一、一切的起点:我写的页面,为什么 SEO 差、首屏慢?
刚入行时,我以为前端就是:
function App() {
const [data, setData] = useState([]);
useEffect(() => {
axios.get('/api/list').then(res => setData(res.data));
}, []);
return <div>{data.map(item => <p>{item.title}</p>)}</div>;
}
上线后,老板问:“为什么百度搜不到我们的商品?”
产品经理问:“用户打开首页要等 3 秒,能不能快点?”
我懵了——我的代码明明跑得好好的啊!
后来才知道:我用的是 CSR(客户端渲染) ,而搜索引擎和用户,看到的只是一个空壳 HTML:
<div id="root"></div>
<script src="main.js"></script>
内容?等 JS 加载完再说吧。
于是,我开始听说 SSR、SSG 这些词。但它们到底是什么?为什么要有三种?能不能统一?
带着这些问题,我花了半年时间,终于搞懂了前端渲染背后的真实逻辑。
今天,我想用最直白的方式,告诉你:这不是三个技术名词,而是一个“不可能三角”的权衡游戏。
📜 二、发展历程:为什么会有这三种模式?
1. CSR(客户端渲染)—— React 的默认姿势
- 起源:
create-react-app、SPA(单页应用)流行。 - 核心思想:所有逻辑交给浏览器,服务器只返回静态文件。
- ✅ 优点:开发简单、部署方便(扔 CDN 就行)、交互灵活。
- ❌ 缺点:首屏白屏、SEO 差、弱网体验崩。
适合场景:后台管理系统、私有应用(如企业 OA、数据看板)。
2. SSR(服务端渲染)—— 回归 Web 本质
- 起源:传统 PHP/JSP 时代,HTML 在服务器拼好再返回。
- 复兴原因:SEO + 首屏性能 成为刚需(电商、内容平台)。
- 核心思想:用户请求时,服务器用 React 渲染出完整 HTML。
- ✅ 优点:首屏快、SEO 友好、用户体验好。
- ❌ 缺点:需要 Node.js 服务器、每次请求消耗 CPU、部署复杂。
适合场景:商品详情页、新闻、用户个人主页。
3. SSG(静态生成)—— 极致性能的妥协
- 起源:JAMStack 架构兴起(Git + CDN + Serverless)。
- 核心思想:在构建时就把所有页面“烤”成 HTML,部署后直接当静态文件分发。
- ✅ 优点:首屏极快、SEO 极佳、零服务器成本、全球 CDN 加速。
- ❌ 缺点:内容必须提前知道,无法实时更新。
适合场景:博客、文档站、营销落地页。
💻 三、写代码有什么不同?关键就看这两个函数!
以 Next.js 为例(Umi 类似),你不需要改组件写法,只需决定是否导出特定函数:
✅ CSR(默认)
// pages/index.js
export default function Home() {
const [user, setUser] = useState(null);
useEffect(() => {
fetch('/api/me').then(r => r.json()).then(setUser);
}, []);
return <div>{user?.name}</div>;
}
// → 没有 getStaticProps / getServerSideProps,就是 CSR!
✅ SSG(构建时生成)
export async function getStaticProps() {
const posts = await fetchPosts(); // 构建时运行!
return { props: { posts } };
}
export default function Home({ posts }) {
return <div>{posts.map(...)}</div>; // 数据直接可用!
}
✅ SSR(请求时生成)
export async function getServerSideProps({ req }) {
const user = await getUserFromCookie(req.headers.cookie); // 每次请求都查!
return { props: { user } };
}
export default function Dashboard({ user }) {
return <div>欢迎,{user.name}!</div>;
}
🔑 核心差异不在 JSX,而在数据获取时机。
组件本身,永远是你熟悉的 React。
🛠️ 四、开发 vs 生产:完整链路拆解
开发环境(next dev)
- 所有模式由同一个开发服务器处理;
- 动态判断页面是否有
getStaticProps/getServerSideProps; - 实时模拟对应行为,无需构建。
生产环境(next build + next start)
| 模式 | 构建产物 | 部署方式 | 请求路径 |
|---|---|---|---|
| CSR | index.html + main.js | CDN / Nginx | 浏览器加载 JS → 渲染 |
| SSG | 预生成的 page.html + JS | CDN / 静态主机 | 直接返回 HTML |
| SSR | Node.js 应用 | Node 服务器 / Serverless | 服务器实时渲染 HTML |
💡 SSG 和 CSR 可部署到 GitHub Pages;SSR 必须用 Vercel、自建服务器等支持 Node 的平台。
⚖️ 五、前端的“不可能三角”:这才是核心!
经过无数项目验证,我发现:
你无法同时满足以下三点:
- 首屏快 + SEO 好(用户/爬虫打开即见内容)
- 数据完全动态、实时(千人千面、随时变)
- 零服务器成本、纯静态部署(CDN 托管、无限扩展)
你只能 三选二:
| 选择 | 模式 | 放弃什么 |
|---|---|---|
| 首屏快 + 静态部署 | SSG | 实时性 |
| 首屏快 + 实时数据 | SSR | 静态部署 |
| 实时数据 + 静态部署 | CSR | 首屏 & SEO |
这不是技术缺陷,而是物理规律——就像 CAP 定理一样,是分布式系统的本质约束。
🌐 六、它们真的互相包含!混合渲染才是常态
现实中,没有哪个项目只用一种模式。聪明的做法是 按页面、甚至按模块混合使用:
// 博客文章页:SSG + CSR
export async function getStaticProps({ params }) {
const post = await getPost(params.slug); // 构建时生成文章
return { props: { post } };
}
export default function Post({ post }) {
const [comments, setComments] = useState([]);
useEffect(() => {
// 浏览器中动态加载评论(个性化内容)
fetchComments(post.id).then(setComments);
}, []);
return (
<>
<article>{post.content}</article> {/* SSG 部分 */}
<Comments comments={comments} /> {/* CSR 部分 */}
</>
);
}
✅ 首屏 SEO 友好(SSG) + 个性化交互(CSR) = 最佳平衡!
Next.js 甚至支持 ISR(增量静态再生) :SSG 页面在访问时自动后台更新,兼顾静态与动态。
🎯 七、给只会写页面的你:如何站在架构角度看问题?
下次接到需求,别急着写 useState,先问三个问题:
- 这个页面需要被搜索引擎收录吗?
→ 是:排除 CSR,考虑 SSG/SSR。 - 内容是否经常变化?是否依赖用户身份?
→ 是:SSR;否:SSG。 - 团队有没有运维 Node.js 服务器的能力?
→ 没有:优先 SSG + CSR 混合。
前端不再是“切图仔”,而是产品体验的第一道防线。
✨ 结语:技术没有银弹,只有权衡
SSR、SSG、CSR 不是三个孤立的技术,而是同一枚硬币的三面。
它们的存在,不是为了增加你的学习负担,而是给你一把调节用户体验与工程成本的旋钮。
当你理解了这个“不可能三角”,你就不再死记概念,而是能根据业务,做出最优选择。
而这,正是从前端 coder 到 frontend architect 的第一步。
如果你觉得这篇文章帮你打通了任督二脉,欢迎点赞、收藏、转发!
让更多还在useEffect里打转的前端朋友,看见更大的世界。
#前端 #SSR #SSG #CSR #Nextjs #Umi #前端架构 #SEO #性能优化 #掘金创作