页面渲染模式
这篇文章本来是为补齐「技术选型」章节而写的,但写着写着发现它本身就是选型决策里权重最大的一环——一旦定了渲染模式,框架、部署、SEO 策略基本就锁死了。所以单独拎出来讲。
一、为什么先讲渲染模式而不是框架
很多团队做技术选型时,第一反应是「选 React 还是 Vue」。但这只是工具,真正的"地基决策"是页面在什么时机、用什么方式生成 HTML——这就是渲染模式(Rendering Mode / Rendering Strategy)。
不同的渲染模式决定了:
- 首屏快不快(FCP / LCP / TTFB 三大指标)
- SEO 友不友好(爬虫能不能拿到内容)
- 部署成本(需不需要 Node 运行时)
- 服务端压力(峰值时打向 Node 的 QPS)
- 交互体验(页面是否有一瞬白屏、是否有 hydration mismatch 闪烁)
下面把主流的 6 种渲染模式一次性讲清。
二、6 种主流渲染模式
1. CSR(Client-Side Rendering,客户端渲染)
核心特点:服务端只返回一个几乎空白的 HTML 壳 + 一个 JS bundle,所有页面内容在浏览器里跑 JS 生成。
执行时机:
请求 ──→ CDN/Nginx 返回空 HTML
↓
浏览器解析 HTML,遇到 <script> 标签
↓
下载、解析、执行 JS bundle(React/Vue runtime + 业务代码 + 数据请求)
↓
JS 在浏览器里 createRoot + render,组件渲染出真实 DOM
↓
页面可见
典型代表:Vite + React/Vue 的纯 SPA 模板(create-react-app、create-vue、Vite 默认模板)
优点:
- 部署最简单,纯静态文件,任何静态服务器都能 serve(Nginx、CDN、GitHub Pages)
- 服务端压力小(HTML 是固定的,缓存到极致)
- 前后端分离彻底,前端可以独立部署
缺点:
- 首屏白屏时间长:JS bundle 越大、网速越慢,白屏越久。3G 环境下可能 3~5 秒
- SEO 极差:爬虫拿到的只有
<div id="root"></div>,看不到任何内容(Googlebot 虽能跑 JS 但要等,百度爬虫基本抓不到) - 数据请求串行化:HTML → JS → API → 渲染,至少 3 个串行网络请求
适用场景:内部后台、管理系统、看板类工具、对 SEO 和首屏速度无要求的应用。
1.5 容易混淆的概念:MPA vs SPA
在聊下面 5 种渲染模式之前,先把两个常被混用、但本质完全不同的概念讲清楚:MPA(多页应用) 和 SPA(单页应用)。
| 维度 | MPA(Multi-Page Application) | SPA(Single-Page Application) |
|---|---|---|
| HTML 数量 | 每个路由对应一个独立的 .html 文件 | 整个应用只有 1 个 index.html |
| 页面切换 | 每次都重新加载整页(浏览器地址栏会有真实跳转) | 不重新加载 HTML,前端路由(History API / Hash)切换组件 |
| 首屏渲染 | 服务端直接吐完整 HTML(一般是 MPA + SSR) | 浏览器跑 JS 渲染(SPA + CSR) |
| 典型代表 | 传统 PHP/Java 网站、jQuery 时代的多页应用、Next.js 用 next/link 之前 | Vite + React 默认模板、Vue Router、React Router |
| 优点 | 简单直接、SEO 天然友好、各页面解耦 | 切换页面无白屏、用户体验"类原生" |
| 缺点 | 每次切换都重新加载 HTML/JS,体验割裂 | 首屏白屏、SEO 差、对前端路由处理要求高 |
关键澄清:
- SPA 不是渲染模式——它是架构形态。判断标准是"页面切换时刷不刷新整个 HTML"
- CSR/SSG/SSR 是渲染模式——它们判断的是"首屏 HTML 是什么时候、怎么生成的"
- 二者正交:可以 SPA + SSR(如 Next.js 用了
next/link,首屏 SSR,后续走 SPA 路由),可以 MPA + CSR(极少见,不推荐),可以 SPA + SSG(如 Gatsby,或 Next.js 的纯静态导出output: export)
为什么现代框架几乎全是 SPA 形态:
因为 SPA 切换页面的体验远胜 MPA(没有白屏、保留 state、动画连贯)。所以即便 Next.js/Astro 默认是 SSG/SSR(首屏吐完整 HTML),它们也都提供了前端路由(next/link、<a> + View Transitions)让用户感觉上是个 SPA。
反直觉的细节:
- 传统 jQuery 时代的多页应用 → MPA + 服务端渲染(连 SSR 都不算,就是 PHP 直接 echo HTML)
- Vite + React 纯前端模板 → SPA + CSR
- Next.js 用了
next/link→ SPA 体验 + SSG/SSR 渲染 - 一个 SSG 静态站加了 View Transitions 动画 → 严格说还是 MPA(多个 HTML),但体感是 SPA
记住一句话:SPA 看路由刷不刷新整页,渲染模式看首屏 HTML 怎么生成——两个维度,互不干扰。
2. SSR(Server-Side Rendering,服务端渲染)
核心特点:每次请求时,Node 服务端实时执行组件代码、生成完整 HTML 返回给浏览器,浏览器拿到 HTML 后再下载 JS 完成水合(hydration)。
执行时机:
请求 ──→ Node 服务端执行 React/Vue 组件代码
↓
调用 API/DB 拿到数据,渲染成 HTML 字符串
↓
返回完整 HTML(带内容)
↓
浏览器立即看到内容(FCP 优秀)
↓
下载 JS bundle 并执行
↓
React/Vue 在客户端「水合」——接管 DOM,绑事件,启动交互
典型代表:Next.js(output: 'server' 或 getServerSideProps)、Nuxt 3(默认)、Remix、SvelteKit(默认)、Express + React 手动实现
优点:
- 首屏极快:浏览器拿到的就是带内容的 HTML,FCP/LCP 都很好
- SEO 友好:HTML 直接带内容,爬虫直接抓
- 数据始终最新:每次请求都重渲染(适合强实时场景,如股票、库存、用户个性化内容)
缺点:
- 服务端压力大:每个请求都要跑一次组件代码、查一次 DB。QPS 高时必须做缓存、负载均衡、扩 Node 实例
- TTFB 受影响:服务端渲染本身有几十~几百 ms 耗时,加上网络 RTT,首字节时间比纯静态差
- 部署成本高:必须常驻 Node 进程,不能像 SSG 那样丢 CDN
- Hydration mismatch 闪烁:服务端渲染和客户端首次渲染结果不一致时(比如用了
Date.now()、Math.random()、window),控制台会报错并强制重渲染 - Node 冷启动:Serverless 部署时冷启动可能 200~500 ms
适用场景:电商商品详情、新闻门户、用户个性化首页、强 SEO 需求 + 实时数据的应用。
3. SSG(Static Site Generation,静态站点生成)
核心特点:构建时(build time)把所有页面一次性渲染成静态 HTML 文件,部署后用户访问的就是这些预先生成的 .html。部署时不再有任何 Node 运行时。
执行时机:
pnpm build
↓
[Astro/Next/Nuxt 编译器]
↓
遍历所有路由,对每个页面跑一次组件代码,生成 .html 文件
↓
产物:dist/ 下有一堆 .html + JS + CSS
↓
部署到 Nginx/CDN/GitHub Pages
↓
用户请求 ──→ 直接返回预先生成的 .html(毫秒级)
典型代表:Astro(默认 SSG)、Next.js(output: 'static' 或 getStaticProps)、Nuxt 3(nuxt generate)、Hugo、Jekyll、11ty、VitePress
优点:
- 首屏极快 + 部署极简:纯静态文件,CDN 全缓存,QPS 扛得住任何量级(淘宝双十一首页是 SSG 的经典案例)
- SEO 极佳:HTML 完整带内容
- 托管便宜:GitHub Pages、Vercel、Netlify、腾讯云 COS、阿里云 OSS 都能直接 serve,几乎零成本
- 安全性高:没有 Node 运行时,攻击面小
缺点:
- 构建时间随页面数线性增长:1 万个页面要构建很久。Next.js 有
ISR缓解,Astro/Hugo 是"全量重 build"模式 - 内容更新延迟:必须重新 build + 重新部署才能更新,对秒级实时数据不友好
- 不适合强个性化:所有用户看到的 HTML 一样,登录态、A/B 测试、地域分发都得靠客户端 JS 二次拉取
适用场景:博客、文档站、营销页、官网、ShaderPad 这种"内容为主 + 轻交互"的工具站。
4. ISR(Incremental Static Regeneration,增量静态再生)
核心特点:SSG + 按需重新生成。首次请求时缓存静态 HTML,后续请求直接返回缓存;缓存过期或主动 revalidate 时,下一个请求触发后台重新生成。
执行时机:
请求 /blog/post-1
↓
[CDN 缓存有吗?]──是──→ 直接返回缓存(毫秒级)
↓ 否
[静态文件存在吗?]──是──→ 返回静态文件 + 后台异步重新生成
↓ 否
Node 服务端实时渲染 HTML ──→ 返回 + 写缓存
典型代表:Next.js(revalidate: 60 或 res.revalidate('/path'))、Nuxt 3(routeRules: { isr: 60 })
优点:
- 兼具 SSG 的速度 + SSR 的实时性:99% 的请求走静态缓存,1% 的请求触发重新生成
- 构建时间不爆炸:1 万个页面也不用一次 build 完,按需生成
缺点:
- 框架支持有限:Next.js 最成熟,Nuxt 3 刚支持,Astro/Hugo 没有
- 部署需要 Node 运行时(虽然大部分请求不走 Node):所以不能纯 CDN 部署
- 缓存一致性略复杂:需要正确配置
revalidate时间和 on-demand revalidation
适用场景:电商商品列表(价格/库存偶尔变)、新闻门户(每小时更新)、大型内容站。
5. RSC(React Server Components,React 服务端组件)
核心特点:React 19 引入的新模式,组件分两种:
- Server Component:在服务端跑,永远不会发到浏览器。可以直接查 DB、读文件、调用内部 API,不暴露任何代码逻辑
- Client Component:传统 React 组件,必须在浏览器跑(
'use client'指令)
执行时机:
请求 ──→ 服务端渲染 RSC 树
↓
[遇到 Server Component] → 在 Node 端跑,组装 UI 树
↓
[遇到 Client Component] → 在 UI 树中插入占位符 + 引用
↓
返回特殊格式的 RSC payload(不是 HTML 也不是 JSON,是 React 自己的流式协议)
↓
浏览器解析 payload → 渲染 Server Component 部分 + 拉取 Client Component 代码
典型代表:Next.js 13+ App Router(默认全部是 RSC,传统组件需要 'use client')、Waku、Parcel
优点:
- 更小的客户端 bundle:Server Component 的代码完全不下发,库、工具函数、数据获取逻辑全部留在服务端
- 直接访问后端资源:不用单独写 API,组件里直接
await db.query(...) - 天然适合数据流:服务端组件可以 await 任意数据,子组件自动 stream 出来
缺点:
- 学习曲线陡:心智模型和传统 React 完全不一样,
'use client'边界要谨慎处理 - 生态还在适应:很多第三方库(特别是 state 管理、动画库)需要
'use client'包装 - 调试和报错相对复杂:服务端组件报错时控制台在 Node 端,浏览器端看到的是"缩小版"错误信息
适用场景:数据密集型应用(Dashboard、Admin)、需要服务端直接访问数据但又要 React 组件树的应用。
6. Astro Islands(群岛架构 / 部分水合)
核心特点:默认全站 SSG(零客户端 JS),但允许在静态海面中插入孤岛(Interactive Islands),孤岛可以独立选择水合时机。每个孤岛都是独立的微型 SPA。
执行时机:
pnpm build
↓
[Astro 编译器]
↓
所有不带 client:* 指令的组件 → 渲染为纯 HTML,JS 全部剥离
↓
带 client:load / client:visible / client:only 等指令的组件 → 渲染为 <astro-island> 占位符,组件及其依赖打成独立 chunk
↓
产物:HTML 极小(只 6~10KB),孤岛 chunk 按需加载
↓
浏览器加载 → 首屏立即可见(FCP 极快)
↓
调度器扫描 <astro-island> → 按指令策略 fetch 组件 chunk + 框架运行时
↓
孤岛完成水合,与周围静态海面完全独立
5 种水合指令:
| 指令 | 触发时机 | 适用场景 |
|---|---|---|
client:load | 页面加载立即 hydrate | 首屏关键交互(导航、登录框) |
client:idle | 浏览器空闲时(requestIdleCallback) | 非关键增强(评论区、推荐位) |
client:visible | 元素进入视口(IntersectionObserver) | 长页面底部的组件(折叠面板、视频) |
client:media | 匹配媒体查询(如 (min-width: 768px)) | 响应式组件(移动端/桌面端不同交互) |
client:only | 跳过任何 SSR,只在客户端渲染 | 强依赖浏览器 API 的(WebGL、Canvas、Audio) |
典型代表:Astro(唯一原生支持)、SolidStart、Qwik City(resumability 思路类似)
优点:
- 首屏极致快:默认零 JS,HTML 极小
- 按需加载颗粒度最细:可以精确到"页面里这个按钮要不要 JS"
- 多框架混用:同一个页面里 React、Vue、Svelte 可以共存
- 部署和 SSG 一样简单:纯静态文件,CDN 全缓存
缺点:
- 不适合强交互 SPA:像 Figma、Notion 这种"整个页面都是交互"的工具,Astro 反而是包袱——所有组件都成孤岛了,跨孤岛状态管理麻烦
- 生态比 Next.js 小:很多 React 生态的库没做 Astro 适配
适用场景:博客、文档站、营销页、「主静态 + 局部重交互」的工具站(ShaderPad、Stripe Docs、Tailwind UI)。
三、6 种模式全景对比
| 模式 | 渲染时机 | SEO | 首屏 | 服务端压力 | 部署复杂度 | 适合场景 |
|---|---|---|---|---|---|---|
| CSR | 浏览器 | ❌ 差 | ❌ 慢(白屏) | ✅ 几乎为零 | ✅ 极简(纯静态) | 后台、内部工具 |
| SSR | 请求时 | ✅ 好 | ✅ 快 | ❌ 高(每请求渲染) | ❌ 需 Node 运行时 | 电商、新闻、个性化 |
| SSG | 构建时 | ✅ 极佳 | ✅ 极快 | ✅ 几乎为零 | ✅ 极简(纯静态) | 文档、博客、营销页 |
| ISR | 构建时 + 按需再生 | ✅ 好 | ✅ 快 | 🟡 低(仅失效时) | 🟡 需 Node 运行时 | 大型内容站、电商列表 |
| RSC | 请求时 | ✅ 好 | ✅ 快 | 🟡 中(仅 RSC 部分) | 🟡 需 Node 运行时 | 数据密集型应用 |
| Astro Islands | 构建时 + 按需 hydrate | ✅ 极佳 | ✅ 极快 | ✅ 几乎为零 | ✅ 极简(纯静态) | 文档+工具混搭站 |
一句话总结:CSR 是反 SEO 的纯前端;SSG/SSR 是 SEO 双雄;SSG 部署最便宜;ISR/RSC 是性能与动态的折中;Astro Islands 是「SSG 的极致」。
四、每种模式对应的主流框架
| 模式 | 代表框架 | 默认渲染 | 备注 |
|---|---|---|---|
| CSR | Vite + React/Vue、create-react-app、create-vue | CSR | 纯静态模板 |
| SSR | Next.js、Nuxt、Remix、SvelteKit、Express + React | 可选 | 同一框架通常支持多种模式 |
| SSG | Astro(默认)、Hugo、Jekyll、VitePress、Next.js(output: 'static') | SSG | Astro 是 SSG 的事实标准 |
| ISR | Next.js、Nuxt 3 | SSG 基础上按需再生 | Next.js 的杀手锏 |
| RSC | Next.js 13+ App Router(默认 RSC)、Waku | RSC | Next.js 在 RSC 上一骑绝尘 |
| Astro Islands | Astro | 群岛 | Astro 独此一家 |
重要观察:Next.js 是唯一同时支持 SSG / SSR / ISR / RSC 四种模式的全能框架。这也是它在前端选型中长期霸榜的原因——选 Next.js 等于"渲染模式可以以后再决定",前期试错成本低。
但代价是 Next.js 的"全"也意味着"重"——同样的需求,如果一开始就明确是 SSG 场景,Astro 的产物会小一个数量级,部署也简单一个数量级。
五、框架横向对比
下表对比的不是渲染模式本身(上面已经讲过),而是「同样想做 SSG/SSR/CSR 的项目,不同框架的差异」:
| 框架 | 底层语言 | 默认模式 | 多框架混用 | 部署形态 | 学习曲线 | 适合项目 |
|---|---|---|---|---|---|---|
| Next.js | React | SSR + RSC | ❌ 仅 React | 需 Node 运行时 | 🟡 中等 | 通用全栈、SEO 站 |
| Nuxt 3 | Vue | SSR | ❌ 仅 Vue | 需 Node 运行时 | 🟢 平缓 | Vue 团队全栈项目 |
| Remix | React | SSR | ❌ 仅 React | 需 Node 运行时 | 🟡 中等 | 强交互 Web App |
| Astro | 多框架 | SSG + 群岛 | ✅ 任意 | 纯静态 | 🟢 最平缓 | 文档/工具混搭站 |
| SvelteKit | Svelte | SSR | ❌ 仅 Svelte | 需 Node 运行时 | 🟢 平缓 | Svelte 粉丝、性能敏感站 |
| Gatsby | React | SSG | ❌ 仅 React | 纯静态 | 🔴 陡(GraphQL 强绑定) | 已被 Astro 取代的方案 |
| Vite + React | React | CSR | ❌ 仅 React | 纯静态 | 🟢 最简单 | 后台、纯 SPA |
几个关键判断点:
- 「必须多框架混用」 → 选 Astro(唯一选项)
- 「团队只会 React」 → Next.js / Vite + React 二选一
- 「强 SEO + 实时数据 + 团队是 React」 → Next.js(用 SSR 或 RSC)
- 「内容为主 + 偶尔有重交互组件」 → Astro
- 「整个页面都是重交互(Notion / Figma 类)」 → 推荐纯 CSR(Vite + React),这类项目不要用 Astro 这类群岛框架
- 「内容站 + 1 万+ 页面 + 数据偶尔变」 → Next.js(用 ISR)
六、针对一个新项目怎么选?
决策树
新项目启动
│
├─ Q1: 需不需要 SEO?
│ │
│ ├─ ❌ 不需要(后台/工具/看板)
│ │ └─ → CSR(Vite + React/Vue)✅ 最简单
│ │
│ └─ ✅ 需要
│ │
│ ├─ Q2: 数据是强实时还是个大概就行?
│ │ │
│ │ ├─ 强实时(电商库存、股票、个性化)
│ │ │ └─ → SSR(Next.js / Nuxt)✅
│ │ │
│ │ └─ 偶尔更新(博客、文档、商品列表)
│ │ │
│ │ ├─ Q3: 页面数 & 团队偏好
│ │ │ │
│ │ │ ├─ 1 万+ 页面 + 团队是 React
│ │ │ │ └─ → ISR(Next.js)✅
│ │ │ │
│ │ │ ├─ 中小规模 + 团队任意
│ │ │ │ └─ → SSG(Astro / Hugo)✅
│ │ │ │
│ │ │ └─ 内容 + 重客户端工具(ShaderPad)
│ │ │ └─ → Astro Islands ✅
│ │ │
│ │ └─ Q3': 数据要从 DB 拉?
│ │ │
│ │ └─ 是 → RSC(Next.js App Router)✅
│ │
│ └─ Q2': 整站强交互(Notion/Figma 类)?
│ │
│ └─ 是 → Next.js / Remix(CSR 模式)✅
4 个典型场景的选型建议
场景 1:企业内部后台 / 管理系统
- 渲染模式:CSR
- 框架:Vite + React + Ant Design / Arco Design
- 部署:纯静态文件 + Nginx
- 理由:无 SEO 需求、整站都是交互、用户登录后使用、白屏几秒无所谓
场景 2:电商官网 / 资讯门户
- 渲染模式:SSR + ISR 混合(首页/列表页用 ISR 缓存、详情页/个人中心用 SSR 实时)
- 框架:Next.js 14+(App Router + RSC)
- 部署:Vercel / 自建 K8s + Node 集群
- 理由:SEO 核心 + 数据强实时 + 团队是 React
场景 3:技术文档站 / 个人博客
- 渲染模式:SSG
- 框架:Astro / VitePress / Docusaurus
- 部署:GitHub Pages / Vercel / 腾讯云 COS 静态托管
- 理由:内容更新频率低、对 SEO 极敏感、想要最便宜的部署
场景 4:在线工具站(ShaderPad / CodePen / Figma)
- 渲染模式:Astro Islands 或 Next.js(CSR 模式)
- 框架:Astro(如果文档 + 工具混搭)或 Vite + React(如果纯工具)
- 部署:纯静态 + CDN
- 理由:内容部分(介绍页/文档)需要 SEO + 加载速度,工具部分(编辑器/画布)是重客户端交互
几个反直觉的提醒
- ❌ 不要为了"用 Next.js"而用 Next.js:如果需求就是 SSG 文档站,Next.js 的产物会比 Astro 大 5~10 倍、部署也比 Astro 复杂
- ❌ 不要给后台加 SSR:白屏时间不会改善,反而引入了 Node 部署成本
- ❌ 不要在 SSG 站点里大量使用
useEffect二次拉数据:相当于把 SSG 退化成了 CSR - ✅ 先决定渲染模式,再选框架:顺序反了很容易后期想换模式时发现框架不支持
七、一句话总结
渲染模式是地基,框架是工具。地基没选好,后期换框架可以、换渲染模式基本等于重写。
最后给一个 quick reference:后台选 CSR、电商选 SSR、内容站选 SSG、大型站选 ISR、复杂 Web App 选 RSC、文档 + 工具混搭选 Astro Islands。