前端渲染模CSR、SSR、SSG、ISR 及相关概念

3 阅读11分钟

1. 先建立一个核心认知

前端常说的 CSR、SSR、SSG、ISR,本质上都在回答同一个问题:

用户访问一个页面时,页面 HTML 是在什么时候、在哪里生成的?

不同答案会影响:

  • 首屏加载速度
  • SEO 效果
  • 服务器压力
  • 页面数据实时性
  • 部署复杂度
  • 前端工程结构
  • 用户交互体验

可以先用一句话记住:

模式一句话理解
CSR浏览器拿到空壳 HTML 后,用 JS 在客户端渲染页面
SSR每次请求时,服务端实时渲染 HTML 后返回
SSG构建项目时提前生成静态 HTML
ISR先静态生成,后续按时间或触发条件增量更新静态页面

这些不是互斥关系。现代框架通常支持混合使用,比如同一个 Next.js 项目里,首页可以 SSG,后台页面可以 CSR,详情页可以 ISR,强实时页面可以 SSR。


2. CSR:Client-Side Rendering,客户端渲染

2.1 CSR 是什么

CSR 是客户端渲染。服务器通常返回一个很简单的 HTML,例如:

<!doctype html>
<html>
	<head>
		<title>CSR App</title>
	</head>
	<body>
		<div id="app"></div>
		<script src="/assets/main.js"></script>
	</body>
</html>

真正的页面内容不在 HTML 里,而是在浏览器下载并执行 JavaScript 后,由 Vue、React 等框架生成。

Vue 典型入口:

// main.ts
import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')

React 典型入口:

// main.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'

ReactDOM.createRoot(document.getElementById('root')!).render(<App />)

2.2 CSR 的请求过程

  1. 浏览器请求页面。
  2. 服务器返回 HTML 空壳。
  3. 浏览器下载 JS、CSS。
  4. JS 执行,框架开始渲染页面。
  5. 页面组件请求接口数据。
  6. 数据返回后,页面更新。

2.3 CSR 的优点

  • 前后端分离清晰,开发体验好。
  • 页面跳转通常很流畅,适合复杂交互。
  • 服务端压力小,主要提供静态资源和 API。
  • 非常适合管理后台、控制台、工作台、编辑器类应用。

2.4 CSR 的缺点

  • 首屏依赖 JS 下载和执行,白屏时间可能较长。
  • SEO 不友好,爬虫如果不执行 JS,拿不到真实内容。
  • 低端设备上 JS 执行慢,体验会下降。
  • 首屏接口请求通常发生在浏览器端,链路更长。

2.5 CSR 适用场景

适合:

  • 后台管理系统
  • SaaS 控制台
  • 数据看板
  • 在线编辑器
  • 内部系统
  • 登录后才能访问的业务页面
  • SEO 不重要、交互复杂的应用

不太适合:

  • 内容站
  • 新闻站
  • 商品详情页
  • 博客文章页
  • 依赖搜索引擎收录的营销页

2.6 CSR 示例:Vue 页面请求数据

<script setup lang="ts">
import { onMounted, ref } from 'vue'

interface Article {
	id: number
	title: string
	summary: string
}

const loading = ref(false)
const articles = ref<Article[]>([])

onMounted(async () => {
	loading.value = true
	try {
		const response = await fetch('/api/articles')
		articles.value = await response.json()
	} finally {
		loading.value = false
	}
})
</script>

<template>
	<section>
		<p v-if="loading">加载中...</p>
		<article v-for="article in articles" :key="article.id">
			<h2>{{ article.title }}</h2>
			<p>{{ article.summary }}</p>
		</article>
	</section>
</template>

这个页面的内容是浏览器运行 JS 后才出现的,这就是典型 CSR。


3. SSR:Server-Side Rendering,服务端渲染

3.1 SSR 是什么

SSR 是服务端渲染。用户每次请求页面时,服务端会先运行前端组件代码,把页面渲染成 HTML 字符串,再返回给浏览器。

浏览器一开始拿到的 HTML 里就有真实内容,例如:

<main>
	<h1>文章标题</h1>
	<p>文章摘要内容...</p>
</main>

之后浏览器再下载 JS,并进行 hydration(水合),让静态 HTML 变成可交互页面。

3.2 Hydration 是什么

Hydration 通常翻译为“水合”。

SSR 返回的 HTML 虽然已经能展示内容,但按钮点击、状态更新、路由切换等交互还不能工作。浏览器下载 JS 后,框架会把事件、状态、组件逻辑绑定到已有 HTML 上,这个过程就是 hydration。

简单理解:

服务端返回可见 HTML
				+
浏览器加载 JS 并绑定交互
				=
完整可交互页面

3.3 SSR 的请求过程

  1. 浏览器请求页面。
  2. 服务端执行页面组件逻辑。
  3. 服务端请求必要数据。
  4. 服务端生成完整 HTML。
  5. 浏览器收到 HTML,立即展示内容。
  6. 浏览器下载 JS。
  7. 框架进行 hydration。
  8. 页面变得可交互。

3.4 SSR 的优点

  • 首屏内容出现更快。
  • SEO 友好,爬虫能直接读取 HTML 内容。
  • 适合弱网环境下优先展示内容。
  • 首屏数据可以在服务端聚合,减少浏览器端等待。

3.5 SSR 的缺点

  • 服务端压力更大,因为每次请求都要渲染。
  • 架构复杂度更高,需要同时考虑服务端和浏览器环境。
  • 代码里不能随意使用 windowdocument 等浏览器专属对象。
  • 容易出现 hydration mismatch(水合不一致)。

3.6 SSR 适用场景

适合:

  • 电商详情页
  • 新闻详情页
  • SEO 重要的内容页
  • 首屏性能要求高的页面
  • 需要根据用户请求实时生成内容的页面
  • 价格、库存、权限等强实时页面

不太适合:

  • 完全登录后的后台系统
  • 高度复杂但 SEO 不重要的交互页面
  • 静态内容很多、更新不频繁的站点

3.7 Next.js SSR 示例

Next.js App Router 中,如果页面使用服务端数据请求,默认就可以在服务端渲染。

// app/articles/[id]/page.tsx
interface ArticlePageProps {
	params: {
		id: string
	}
}

async function getArticle(id: string) {
	const response = await fetch(`https://example.com/api/articles/${id}`, {
		cache: 'no-store'
	})

	if (!response.ok) {
		throw new Error('文章加载失败')
	}

	return response.json()
}

export default async function ArticlePage({ params }: ArticlePageProps) {
	const article = await getArticle(params.id)

	return (
		<main>
			<h1>{article.title}</h1>
			<p>{article.summary}</p>
			<article>{article.content}</article>
		</main>
	)
}

关键点:

cache: 'no-store'

这表示每次请求都重新获取数据,更接近 SSR 的实时渲染。

3.8 Nuxt SSR 示例

Nuxt 默认支持 SSR。

<!-- pages/articles/[id].vue -->
<script setup lang="ts">
const route = useRoute()

const { data: article } = await useFetch(`/api/articles/${route.params.id}`)
</script>

<template>
	<main v-if="article">
		<h1>{{ article.title }}</h1>
		<p>{{ article.summary }}</p>
		<article>{{ article.content }}</article>
	</main>
</template>

服务端会先执行 useFetch,拿到数据后再渲染页面 HTML。


4. SSG:Static Site Generation,静态站点生成

4.1 SSG 是什么

SSG 是静态生成。页面不是用户请求时才生成,而是在项目构建时提前生成 HTML 文件。

例如构建后可能得到:

dist/
	index.html
	about/index.html
	articles/1/index.html
	articles/2/index.html

用户访问时,服务器或 CDN 直接返回这些静态 HTML 文件。

4.2 SSG 的请求过程

构建阶段:

  1. 执行构建命令。
  2. 框架读取数据源。
  3. 为每个页面生成 HTML。
  4. 把 HTML、CSS、JS 输出到静态目录。

访问阶段:

  1. 浏览器请求页面。
  2. CDN 或静态服务器直接返回 HTML。
  3. 浏览器展示页面。
  4. JS 加载后进行交互增强。

4.3 SSG 的优点

  • 访问速度非常快。
  • 可以直接部署到 CDN。
  • 服务端成本低。
  • 安全性较高,因为不需要运行复杂服务端逻辑。
  • SEO 友好。

4.4 SSG 的缺点

  • 数据更新后通常需要重新构建。
  • 页面数量极多时,构建时间会变长。
  • 不适合每次访问都需要实时数据的页面。

4.5 SSG 适用场景

适合:

  • 文档站
  • 博客
  • 官网
  • 营销页
  • 帮助中心
  • 更新频率低的内容页面
  • 可以接受分钟级或发布级延迟的数据页面

不太适合:

  • 股票行情
  • 实时库存
  • 实时搜索结果
  • 用户个性化页面
  • 强权限页面

4.6 Next.js SSG 示例

如果使用 generateStaticParams,Next.js 可以在构建时生成静态页面。

// app/articles/[id]/page.tsx
interface ArticlePageProps {
	params: {
		id: string
	}
}

async function getArticles() {
	const response = await fetch('https://example.com/api/articles')
	return response.json()
}

async function getArticle(id: string) {
	const response = await fetch(`https://example.com/api/articles/${id}`)
	return response.json()
}

export async function generateStaticParams() {
	const articles = await getArticles()

	return articles.map((article: { id: number }) => ({
		id: String(article.id)
	}))
}

export default async function ArticlePage({ params }: ArticlePageProps) {
	const article = await getArticle(params.id)

	return (
		<main>
			<h1>{article.title}</h1>
			<p>{article.summary}</p>
		</main>
	)
}

构建时,框架会根据 generateStaticParams 返回的 id 列表提前生成页面。

4.7 Nuxt SSG 示例

Nuxt 可以通过静态生成输出页面:

// nuxt.config.ts
export default defineNuxtConfig({
	ssr: true,
	nitro: {
		prerender: {
			routes: ['/', '/about', '/articles/1', '/articles/2']
		}
	}
})

构建命令通常类似:

nuxi generate

生成后的内容可以部署到静态服务器或 CDN。


5. ISR:Incremental Static Regeneration,增量静态再生成

5.1 ISR 是什么

ISR 可以理解为 SSG 的增强版。

SSG 的问题是:页面构建后,如果数据变了,需要重新构建整个站点或相关页面。ISR 允许页面先静态生成,然后在运行时按策略更新部分页面。

简单理解:

第一次:使用构建时生成的静态 HTML
过一段时间:后台重新生成这个页面
后续访问:拿到更新后的静态 HTML

5.2 ISR 的典型策略

常见有两种:

  1. 按时间重新生成:比如每 60 秒最多更新一次。
  2. 按事件触发更新:比如 CMS 发布文章后,通过 webhook 通知框架重新生成页面。

5.3 ISR 的优点

  • 接近 SSG 的访问速度。
  • 数据可以自动更新。
  • 不需要每次请求都 SSR,服务端压力较小。
  • 适合大量内容页面。

5.4 ISR 的缺点

  • 数据不是绝对实时。
  • 需要理解缓存和重新生成时机。
  • 用户可能短时间内看到旧内容。
  • 部署平台需要支持相关能力。

5.5 ISR 适用场景

适合:

  • 商品详情页
  • 新闻详情页
  • 博客文章页
  • 课程详情页
  • 文档页面
  • 大量内容页,但不要求秒级实时

不太适合:

  • 金融交易
  • 秒杀库存
  • 实时权限判断
  • 用户个人中心
  • 必须每次请求都准确的数据页

5.6 Next.js ISR 示例:按时间更新

// app/products/[id]/page.tsx
interface ProductPageProps {
	params: {
		id: string
	}
}

async function getProduct(id: string) {
	const response = await fetch(`https://example.com/api/products/${id}`, {
		next: {
			revalidate: 60
		}
	})

	if (!response.ok) {
		throw new Error('商品加载失败')
	}

	return response.json()
}

export default async function ProductPage({ params }: ProductPageProps) {
	const product = await getProduct(params.id)

	return (
		<main>
			<h1>{product.name}</h1>
			<p>价格:{product.price}</p>
			<p>库存:{product.stock}</p>
		</main>
	)
}

关键点:

next: {
	revalidate: 60
}

这表示页面相关数据最多缓存 60 秒。超过时间后,下一次访问会触发重新验证和页面更新。

5.7 Next.js ISR 示例:页面级 revalidate

// app/news/[id]/page.tsx
export const revalidate = 300

export default async function NewsPage({ params }: { params: { id: string } }) {
	const response = await fetch(`https://example.com/api/news/${params.id}`)
	const news = await response.json()

	return (
		<main>
			<h1>{news.title}</h1>
			<article>{news.content}</article>
		</main>
	)
}

revalidate = 300 表示这个页面大约每 300 秒可以重新生成一次。


6. 其他常见说法

除了 CSR、SSR、SSG、ISR,前端渲染体系里还经常出现下面这些词。

6.1 SPA:Single Page Application,单页应用

SPA 指单页应用。它通常和 CSR 一起出现,但二者不是完全等价。

SPA 的特点:

  • 初次加载一个 HTML。
  • 后续页面切换由前端路由控制。
  • 页面不整体刷新。
  • 常见于 Vue Router、React Router 应用。

示例:

// router.ts
import { createRouter, createWebHistory } from 'vue-router'

export const router = createRouter({
	history: createWebHistory(),
	routes: [
		{ path: '/', component: () => import('./pages/Home.vue') },
		{ path: '/users', component: () => import('./pages/UserList.vue') }
	]
})

后台管理系统大多是 SPA + CSR。

6.2 MPA:Multi-Page Application,多页应用

MPA 指多页应用。传统网站通常是 MPA。

特点:

  • 每个页面都有独立 HTML。
  • 页面跳转时浏览器会请求新页面。
  • 可以由后端模板、SSR、SSG 等方式生成。

传统后端模板示例:

<!-- article.html -->
<html>
	<body>
		<h1>{{ article.title }}</h1>
		<p>{{ article.summary }}</p>
	</body>
</html>

6.3 Prerender:预渲染

Prerender 是一个比较泛的词,意思是提前把页面渲染成 HTML。

它可能指:

  • 构建时预生成 HTML,接近 SSG。
  • 对部分路由生成 HTML,用于改善 SEO。
  • 使用爬虫式工具打开页面并保存渲染结果。

Vite SPA 项目如果需要少量 SEO 页面,有时会使用预渲染插件。

6.4 Dynamic Rendering:动态渲染

Dynamic Rendering 通常指:

  • 普通用户访问时返回 CSR 页面。
  • 搜索引擎爬虫访问时返回预渲染或 SSR 页面。

它更多是历史过渡方案。现在如果 SEO 很重要,通常更推荐直接使用 SSR、SSG 或 ISR。

6.5 Streaming SSR:流式服务端渲染

普通 SSR 往往要等完整 HTML 准备好后再返回。Streaming SSR 可以把 HTML 分块逐步返回。

好处:

  • 用户能更早看到页面骨架或部分内容。
  • 慢数据区域可以后返回。
  • 适合复杂页面。

React Suspense 示例:

import { Suspense } from 'react'

function ProductInfo() {
	return <section>商品基础信息</section>
}

async function Reviews() {
	const response = await fetch('https://example.com/api/reviews')
	const reviews = await response.json()

	return <section>{reviews.length} 条评价</section>
}

export default function ProductPage() {
	return (
		<main>
			<ProductInfo />
			<Suspense fallback={<p>评价加载中...</p>}>
				<Reviews />
			</Suspense>
		</main>
	)
}

6.6 Edge Rendering / Edge SSR,边缘渲染

Edge Rendering 是把渲染逻辑放到离用户更近的边缘节点上执行。

例如用户在北京,就尽量在北京附近的边缘节点生成页面,而不是回源到很远的中心服务器。

适合:

  • 全球用户访问
  • 低延迟要求
  • 个性化但逻辑不太重的页面

注意:边缘运行时通常有限制,不一定支持完整 Node.js API。

6.7 Islands Architecture,岛屿架构

岛屿架构的思想是:页面大部分内容是静态 HTML,只有少数需要交互的区域加载 JS。

比如一篇文章页面:

  • 标题、正文、作者信息是静态的。
  • 评论框、点赞按钮、收藏按钮是可交互的岛屿。

好处:

  • 大幅减少客户端 JS。
  • 首屏快。
  • SEO 好。
  • 适合内容站。

Astro 是岛屿架构的代表框架。

Astro 示例:

---
import LikeButton from '../components/LikeButton.jsx'
const article = await fetchArticle(Astro.params.id)
---

<main>
	<h1>{article.title}</h1>
	<article>{article.content}</article>
	<LikeButton client:load articleId={article.id} />
</main>

client:load 表示这个组件需要在客户端加载并具备交互能力。

6.8 Partial Hydration,部分水合

部分水合指只让页面中需要交互的部分加载 JS 并绑定事件。

它和岛屿架构关系很近,目标都是减少不必要的客户端 JS。

6.9 Progressive Hydration,渐进水合

渐进水合指页面不是一次性完成所有 hydration,而是根据优先级逐步完成。

例如:

  • 首屏按钮先水合。
  • 页尾评论区等用户滚动到附近再水合。
  • 低优先级组件延迟水合。

6.10 RSC:React Server Components,React 服务端组件

RSC 是 React 的一种新组件模型。它允许某些组件只在服务端执行,不把对应 JS 发送到浏览器。

它和 SSR 有关系,但不是同一个概念。

区别:

概念重点
SSR把页面在服务端渲染成 HTML
RSC组件可以在服务端执行,并减少客户端 JS

Next.js App Router 默认组件就是 Server Component。

// 默认是 Server Component
export default async function ArticleList() {
	const response = await fetch('https://example.com/api/articles')
	const articles = await response.json()

	return (
		<ul>
			{articles.map((article: { id: number; title: string }) => (
				<li key={article.id}>{article.title}</li>
			))}
		</ul>
	)
}

如果组件需要浏览器事件,需要加 'use client'

'use client'

import { useState } from 'react'

export function Counter() {
	const [count, setCount] = useState(0)

	return <button onClick={() => setCount(count + 1)}>{count}</button>
}

7. 不同模式对比

7.1 核心对比表

模式HTML 生成时机HTML 生成位置SEO首屏数据实时性服务器压力典型场景
CSR浏览器运行时客户端较弱依赖 JS后台、控制台、复杂交互
SSR每次请求时服务端内容详情、电商、实时页面
SSG构建时构建机器很好很低文档、博客、官网
ISR构建时 + 运行时增量更新服务端/CDN 平台很好中低商品、新闻、课程、文章

7.2 按业务场景选型

场景推荐模式原因
后台管理系统CSR登录后访问,SEO 不重要,交互复杂
企业官网SSG内容稳定,访问速度和 SEO 重要
博客SSG 或 ISR文章不需要每次实时计算
新闻站首页SSR 或 ISR需要 SEO,也需要一定更新频率
新闻详情页ISR页面多,适合静态缓存和增量更新
商品详情页ISR 或 SSR商品信息可缓存,价格库存强实时时用 SSR/API 补充
搜索结果页SSR 或 CSR搜索结果实时性强,也可登录后 CSR
用户个人中心CSR 或 SSR个性化强,SEO 不重要
文档站SSG内容稳定,CDN 友好
股票行情CSR + 实时 API数据变化快,HTML 静态意义不大
营销活动页SSG 或 SSR需要 SEO 和首屏表现

8. 实际项目里怎么组合

真实项目通常不是只用一种模式,而是组合使用。

8.1 电商项目示例

页面推荐模式
首页ISR
商品列表SSR 或 ISR
商品详情ISR
购物车CSR
订单页CSR
支付页SSR 或 CSR
帮助中心SSG

商品详情页可以这样拆:

  • 商品标题、图片、描述:ISR 生成。
  • 实时价格:客户端请求 API 更新。
  • 实时库存:客户端请求 API 更新。
  • 推荐商品:可 ISR 或 CSR。

示例:

// app/products/[id]/page.tsx
import StockPanel from './StockPanel'

export const revalidate = 300

export default async function ProductPage({ params }: { params: { id: string } }) {
	const response = await fetch(`https://example.com/api/products/${params.id}`)
	const product = await response.json()

	return (
		<main>
			<h1>{product.name}</h1>
			<p>{product.description}</p>
			<StockPanel productId={params.id} />
		</main>
	)
}
// app/products/[id]/StockPanel.tsx
'use client'

import { useEffect, useState } from 'react'

export default function StockPanel({ productId }: { productId: string }) {
	const [stock, setStock] = useState<number | null>(null)

	useEffect(() => {
		fetch(`/api/products/${productId}/stock`)
			.then((response) => response.json())
			.then((data) => setStock(data.stock))
	}, [productId])

	return <p>实时库存:{stock ?? '加载中...'}</p>
}

这样既保留了 ISR 的 SEO 和速度,又能保证关键动态数据及时更新。

8.2 后台系统示例

后台系统通常更适合 CSR:

<script setup lang="ts">
import { onMounted, ref } from 'vue'

interface User {
	id: number
	name: string
	role: string
}

const users = ref<User[]>([])

onMounted(async () => {
	const response = await fetch('/api/admin/users')
	users.value = await response.json()
})
</script>

<template>
	<table>
		<thead>
			<tr>
				<th>姓名</th>
				<th>角色</th>
			</tr>
		</thead>
		<tbody>
			<tr v-for="user in users" :key="user.id">
				<td>{{ user.name }}</td>
				<td>{{ user.role }}</td>
			</tr>
		</tbody>
	</table>
</template>

原因:

  • 页面需要登录。
  • SEO 没意义。
  • 权限和状态都在客户端交互中频繁变化。
  • 表格、表单、弹窗、筛选很多,CSR 开发效率高。

9. 常见性能指标如何受影响

学习渲染模式时,也要理解几个性能指标。

9.1 FCP:First Contentful Paint

首次内容绘制。用户第一次看到文字、图片等内容的时间。

SSG、SSR、ISR 通常对 FCP 更友好,因为 HTML 里已经有内容。

9.2 LCP:Largest Contentful Paint

最大内容绘制。通常衡量首屏最大图片或文本块出现的时间。

SSR/SSG/ISR 可以改善 LCP,但图片优化、接口速度、CDN 同样重要。

9.3 TTI:Time to Interactive

页面变得可交互的时间。

SSR 虽然能快速展示内容,但如果 JS 很大,hydration 仍然可能很慢。

9.4 TTFB:Time to First Byte

浏览器收到第一个字节的时间。

  • CSR 静态资源通常 TTFB 低。
  • SSR 每次要服务端计算,TTFB 可能更高。
  • SSG/ISR 命中缓存时 TTFB 通常较低。

10. 常见坑

10.1 SSR 中直接使用 window 或 document

错误示例:

const width = window.innerWidth

SSR 时服务端没有 window,会报错。

修复方式:

import { onMounted, ref } from 'vue'

const width = ref(0)

onMounted(() => {
	width.value = window.innerWidth
})

React 中可以放到 useEffect

'use client'

import { useEffect, useState } from 'react'

export function WindowWidth() {
	const [width, setWidth] = useState(0)

	useEffect(() => {
		setWidth(window.innerWidth)
	}, [])

	return <span>{width}</span>
}

10.2 Hydration mismatch

服务端渲染出来的 HTML 和客户端首次渲染结果不一致,就可能出现 hydration mismatch。

常见原因:

  • 服务端和客户端时间不同。
  • 使用随机数。
  • 根据浏览器环境渲染不同内容。
  • 服务端数据和客户端数据不一致。

容易出问题的代码:

export default function Page() {
	return <p>{Date.now()}</p>
}

服务端生成一个时间,客户端 hydration 时又生成另一个时间,结果不一致。

10.3 把所有页面都 SSR

SSR 不是银弹。后台系统、强交互页面、SEO 不重要页面,不一定需要 SSR。

错误思路:

SSR 首屏快,所以所有页面都 SSR

更合理的思路:

需要 SEO 或首屏内容可见性的页面才优先考虑 SSR/SSG/ISR
强交互和登录后页面优先考虑 CSR

10.4 ISR 误以为是实时

ISR 不是实时渲染。它有缓存周期和重新生成过程。

如果页面必须每次请求都返回最新数据,应该用 SSR 或客户端实时 API。

10.5 SSG 页面太多导致构建很慢

如果有几百万个商品详情页,全部 SSG 会导致构建非常慢。

此时可以考虑:

  • 热门页面预生成。
  • 长尾页面按需生成。
  • 使用 ISR。
  • 使用 SSR + 缓存。

11. 简单决策流程

可以按下面的问题判断:

11.1 页面需要 SEO 吗?

  • 不需要:优先 CSR。
  • 需要:继续判断。

11.2 页面内容是否经常变化?

  • 很少变化:SSG。
  • 偶尔变化:ISR。
  • 每次访问都要最新:SSR。

11.3 页面是否高度个性化?

  • 是:CSR 或 SSR。
  • 否:SSG 或 ISR。

11.4 页面是否有大量交互?

  • 是:CSR 或局部客户端组件。
  • 否:SSG/SSR/ISR 都可以。

可以粗略记成:

后台系统:CSR
静态内容:SSG
内容多且会更新:ISR
强实时 + SEO:SSR
静态内容 + 少量交互:岛屿架构 / 部分水合

12. 常见框架能力对照

框架CSRSSRSSGISR说明
Vue + Vite需要额外方案需要插件或框架适合 SPA 和后台
Nuxt有相关能力Vue SSR/SSG 主流方案
React + Vite需要额外方案需要插件或框架适合 SPA
Next.jsReact 全栈框架
Astro支持支持视部署而定内容站和岛屿架构强
SvelteKit视部署而定Svelte 全栈框架

13. 学习建议

建议按这个顺序学:

  1. 先学 CSR:理解浏览器、路由、组件、接口请求。
  2. 再学 SSR:理解服务端生成 HTML、水合、服务端数据获取。
  3. 再学 SSG:理解构建时生成页面、静态部署、CDN。
  4. 再学 ISR:理解缓存、重新验证、内容更新策略。
  5. 最后学 Streaming SSR、RSC、岛屿架构、部分水合等进阶概念。

实践路线:

  1. 用 Vue 或 React 写一个 CSR 后台列表页。
  2. 用 Next.js 或 Nuxt 写一个 SSR 文章详情页。
  3. 用 SSG 生成一个博客。
  4. 用 ISR 做一个商品详情页。
  5. 对比每种页面的 HTML 源码、首屏速度和接口请求时机。

学习时可以重点观察:

  • 打开“查看网页源代码”,HTML 里有没有真实内容。
  • 打开 Network 面板,看数据接口是在服务端请求还是浏览器请求。
  • 禁用 JavaScript 后,页面还能不能看到核心内容。
  • 刷新页面时,首屏内容出现速度如何。
  • 搜索引擎是否能直接读取内容。

14. 总结

CSR、SSR、SSG、ISR 都是前端页面渲染策略,不是单纯的框架名词。

最重要的区别是:

模式核心问题答案
CSRHTML 在浏览器里由 JS 生成
SSRHTML 在服务端每次请求时生成
SSGHTML 在构建阶段提前生成
ISRHTML 先静态生成,再按策略增量更新

真正做项目时,不要追求某一种模式“最先进”,而要看业务需要:

  • SEO 重要吗?
  • 首屏速度重要吗?
  • 数据要多实时?
  • 页面是不是个性化?
  • 服务器成本能不能接受?
  • 页面交互复杂吗?

能回答这些问题,就能判断该用 CSR、SSR、SSG、ISR,还是它们的组合。