四種渲染模式
四種渲染模式(SSG / SSR / ISR / CSR)
TL;DR四種模式對應「HTML 何時生成」 :
- SSG — build 時生成,適合 靜態內容(部落格、文件、行銷頁)
- SSR — 每次 request 生成,適合 動態 / 個人化內容
- ISR — build 生成 + 背景重生,適合 半靜態(商品頁、新聞)
- CSR — browser 跑 JS 才有內容,適合 互動高的 app
2026 年加上 Server Components / Streaming / PPR(Partial Prerendering),Next.js 把這些混合成更彈性的渲染策略。
四種模式快速對照
| 模式 | HTML 生成時機 | 動態資料 | SEO | 首屏速度 | Server 成本 |
|---|---|---|---|---|---|
| SSG | build 時 | ❌ 靜態 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ 最快 | 0 |
| SSR | 每次 request | ✅ 即時 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | 高 |
| ISR | build + 背景重生 | ✅ 半新 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | 低 |
| CSR | browser 跑 JS 才有 | ✅ 即時 | ❌ 弱 | ⭐⭐ 慢 | 0 |
SSG(Static Site Generation)
靜態網站產生器。在 build 時 把所有頁面 預先生成 HTML,部署後直接給 user。
// Next.js — Pages Router
export async function getStaticProps() {
const posts = await fetchPosts();
return { props: { posts } }; // ⭐ build 時跑一次,結果寫進 HTML
}
// Next.js — App Router(預設)
export default async function Page() {
const posts = await fetchPosts({ cache: 'force-cache' }); // ⭐ 同效果
return <PostList posts={posts} />;
}
優點
- 最快:HTML 直接從 CDN 給,毫秒級
- SEO 滿分:Google 拿到完整 HTML
- Server 成本 0:純靜態檔
- 安全性高:沒 server-side process,攻擊面極小
缺點
- 內容變動需 rebuild:1000 頁就要 build 1000 次
- 大型網站 build 時間爆炸:成千上萬商品頁 build 一次要幾小時
- 不適合動態內容:即時資料、user-specific 都不行
何時用 SSG
✅ 適合:部落格、文件、行銷頁、個人作品集、產品介紹 ❌ 不適合:任何 每分鐘變動 的內容
SSR(Server-Side Rendering)
伺服器端渲染。每次 request 進來,server 即時生成 HTML 回傳。
// Next.js — Pages Router
export async function getServerSideProps(ctx) {
const user = await fetchUser(ctx.req.cookies.session);
return { props: { user } };
}
// Next.js — App Router
export default async function Page() {
const user = await fetchUser({ cache: 'no-store' }); // ⭐ 每次都重撈
return <Dashboard user={user} />;
}
優點
- 動態資料:可 server-side fetch user-specific 內容
- SEO:Google 拿到完整 HTML
- 認證 friendly:在 server 驗 cookie / token
缺點
- Server 負擔重:每個 request 都要 render
- TTFB 慢:user 等 server 處理完才看到內容
- 配置複雜:cache 策略、CDN 整合
- 攻擊面大:server-side 漏洞風險
何時用 SSR
✅ 適合:dashboard、個人化頁面、購物車、即時報價 ❌ 不適合:純靜態內容(浪費 server 資源)
ISR(Incremental Static Regeneration)
SSG + 背景定期重生。最初像 SSG,但會 根據 revalidate 規則背景更新。
// Next.js — Pages Router
export async function getStaticProps() {
const products = await fetchProducts();
return {
props: { products },
revalidate: 60, // ⭐ 每 60 秒檢查一次
};
}
// Next.js — App Router
const products = await fetch(url, {
next: { revalidate: 60 },
});
工作原理
首次 request → SSG 預生成的舊 HTML 直接回(快)
↓
背景檢查 revalidate 過期沒
↓
過期了 → 背景 fetch 新資料 + render 新 HTML
↓
下次 request → 拿到新 HTML
Stale-While-Revalidate 概念:user 永遠看到 cache,背景默默更新。
優點
- 快(SSG-like 速度)
- 半新資料(可接受 N 秒誤差)
- Server 成本低(只在過期時 render)
- 大型網站 friendly(不用一次 build 全部)
缺點
- 過期容忍:user 可能看到 N 秒前的資料
- revalidate 邏輯複雜:invalidation 不直觀
- 只 Next.js / Vercel-like 平台支援
何時用 ISR
✅ 適合:商品頁、新聞、文章列表(分鐘級延遲 OK) ❌ 不適合:即時股價、聊天訊息(秒級延遲都不能容忍)
CSR(Client-Side Rendering)
客戶端渲染。Server 回 空 HTML + JS bundle,browser 跑 JS 才填內容。
// 純 React SPA(CRA / Vite)
function App() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('/api/data').then((r) => r.json()).then(setData);
}, []);
return data ? <Content data={data} /> : <Skeleton />;
}
優點
- Server 成本 0(只 host 靜態 assets)
- 互動性最強(全 JS,動畫流暢)
- 頁面切換快(SPA 不重新整理)
缺點
- SEO 弱:Google 拿到空 HTML(雖然現在會跑 JS,但 indexing 較不穩)
- 首屏慢:JS bundle 下載 → parse → 執行 → fetch → render
- 白屏問題:JS 跑完前 user 看不到任何東西
- 易受 XSS / CSRF 等前端攻擊
何時用 CSR
✅ 適合:後台工具、內部 dashboard、需要極高互動性的 app(白板、編輯器) ❌ 不適合:任何需要 SEO 的內容、首屏速度敏感的頁面
安全性對比
| 模式 | 安全性 | 主要風險 |
|---|---|---|
| SSG | ⭐⭐⭐⭐⭐ | 攻擊面最小(純靜態) |
| SSR | ⭐⭐⭐⭐⭐ | server 漏洞 / 配置錯誤 |
| ISR | ⭐⭐⭐⭐ | 介於 SSG 跟 SSR |
| CSR | ⭐⭐ | XSS / CSRF / token 暴露 |
CSR 最危險:client 端是駭客主場。Auth 邏輯、token、敏感資料都得在 server 處理(詳見 限制特定網頁)。
2026 新觀念:Server Components + Streaming + PPR
Next.js App Router 把這四種模式重新定義。
Server Components(RSC)
預設所有 component 都在 server 跑,client 只收 HTML + 必要的 hydration JS:
// app/page.tsx — Server Component(預設)
export default async function Page() {
const data = await db.posts.findMany(); // ⭐ 直接 await,不用 useEffect
return <PostList posts={data} />;
}
// 需要互動才用 Client Component
'use client';
function LikeButton() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}
結果:
- Bundle 變小(只 ship 互動部分的 JS)
- SEO 完整(server render 完整 HTML)
- 首屏快(不用等 client fetch)
Streaming + Suspense
讓頁面分段串流給 client,慢的部分先給 skeleton:
import { Suspense } from 'react';
export default function Page() {
return (
<>
<Header /> {/* 快,直接出 */}
<Suspense fallback={<Skeleton />}>
<SlowDashboard /> {/* 慢,先 skeleton 後填 */}
</Suspense>
<Footer />
</>
);
}
使用者看到 Header 時,Dashboard 還在 fetch。比 SSR 等所有資料完才送更友善。
PPR(Partial Prerendering)
2024 出現的混合模式:
- 靜態 shell 預先 render(SSG-like 快)
- 動態洞 在 request 時 stream(SSR-like 即時)
// Next.js 14+
export const experimental_ppr = true;
export default async function ProductPage() {
return (
<>
<ProductImage /> {/* 預先 render */}
<ProductTitle /> {/* 預先 render */}
<Suspense fallback={<PriceSkeleton />}>
<DynamicPrice /> {/* 即時 stream(個人化價格) */}
</Suspense>
</>
);
}
SSG + SSR 兩種模式合一,前端設計史的進化。
各模式選型決策樹
這個頁面內容對所有 user 都一樣?
├── 是 → 變動頻率多高?
│ ├── 幾乎不變 → ==SSG==(部落格、文件)
│ ├── 分鐘級 → ==ISR==(商品頁、新聞)
│ └── 秒級 → ==SSR==(股價、訂單列表)
│
└── 否(個人化) → 需要 SEO 嗎?
├── 是 → ==SSR / RSC==(個人化 dashboard 但要被 index)
└── 否 → ==CSR==(後台、編輯器)
2026 年實務建議
- 新專案:Next.js App Router + Server Components 為預設
- 互動高的部分:
'use client'(類似 CSR)- 慢的資料:Suspense + streaming
- 半靜態:
fetch({ next: { revalidate } })- 完全靜態:
{ cache: 'force-cache' }(預設)四種模式不再是「選一個」,而是「同一頁面內混搭」。
在 BoboBlog 的應用
我自己的 BoboBlog 用 Next.js App Router:
| 區段 | 渲染模式 |
|---|---|
| 首頁 | SSG(force-cache,build 時生成) |
| 文章列表 | SSG + 內容更新時 revalidatePath |
| 文章內頁 | SSG(每篇文章一個 static page) |
| 搜尋結果 | CSR(client filter) |
| Auth 限制頁 | (規劃中)middleware + RSC |
99% 流量走 SSG,直接從 CDN 拿,server 成本接近 0。