網頁渲染(Rendering)是將 HTML
、JavaScript
、資料等代碼,轉換為使用者肉眼可見網頁畫面的過程。
從網頁開發的角度中,渲染通常涉及將資料和網頁模板結合,生成最終顯示在瀏覽器中的 DOM(Document Object Model)結構。
渲染的方式有很多,雖然對使用者而言都大同小異,都是點擊網頁後,等待頁面載入後看到畫面。但不同渲染方式背後的處理邏輯、影響卻大不相同。
渲染處理得好不好,會直接影響到UX、SEO 與伺服器效能。
- UX:影響頁面載入速度、初始畫面顯示速度,從而影響用戶的使用體驗。
- SEO:搜尋引擎爬蟲如何檢索和索引網站內容,會直接受到網頁渲染模式的影響。
- 伺服器效能:正確選擇渲染方式能降低伺服器負擔,並加快頁面的載入速度。
目前在網頁開發上,主要有 4 種頁面渲染技術, 每種方式在資料傳遞與適用情境上都略有差異。
渲染方式 | 全名 | 中文名稱 |
---|---|---|
CSR | Client-Side Rendering | 客戶端渲染 |
SSR | Server-Side Rendering | 伺服器端渲染 |
SSG | Static Site Generation | 靜態網站生成 |
ISR | Incremental Static Regeneration | 增量靜態重新生成 |
本文會介紹以上提及的 4 種渲染方式,並且以 React 框架開發網頁為範例說明。
文章大綱
客戶端渲染 CSR
CSR(Client-Side Rendering)是將所有的渲染工作交由瀏覽器(客戶端)進行,伺服器僅提供一個基礎的 HTML 文件,瀏覽器通過 JavaScript 動態渲染呈現畫面,能透過 API 取得資料,並且更新頁面內容。
CSR 的特色是能對於伺服器的負擔較小,可以將部分的網頁載入需求分配給瀏覽器完成,因此對瀏覽器負擔較大,畫面的載入時間也會相對較慢。
由於多數的網路爬蟲、搜尋引擎爬蟲都是直接透伺服器跟網站 request
網頁資料,直接透過對方 response
的內容分析網頁。因此 CSR 的內容對爬蟲程式較不友善,
如果有規劃要做 SEO,使用 CSR 開發的網站就需要使用額外的預渲染 (Pre-rendering)或 SSR 技術輔助。
Google 官方表示過數次,他們的搜尋引擎爬蟲 Googlebot 能讀懂 CSR 製作的頁面。但實際觀察下來, CSR 的頁面普遍檢索效率較差,難有很好的 SEO 表現。
CSR 的渲染步驟

- 用戶請求 HTML 文件。
- 伺服器回傳基本的 HTML 結構(通常只有一個空的
<div id='root'>
容器)。 - 瀏覽器載入 JavaScript 資源,在瀏覽器端啟動,通過 API 獲取資料。
- JS 在客戶端生成 DOM 結構,渲染頁面
- 用戶最終看到完整的頁面內容。
React.js 實現動態渲染
my-app/
├─ public/
│ ├─ index.html # 僅有一個基本的 HTML 容器
├─ src/
│ ├─ App.js # React 主組件
│ ├─ index.js # React 應用入口
│ ├─ components/ # UI 元件
│ ├─ pages/ # 應用頁面
public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>CSR Example</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
src/App.js
import React, { useEffect, useState } from 'react';
const App = () => {
const [data, setData] = useState(null);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/posts/1')
.then((response) => response.json())
.then((data) => setData(data));
}, []);
if (!data) return <div>Loading...</div>;
return (
<div>
<h1>{data.title}</h1>
<p>{data.body}</p>
</div>
);
};
export default App;
伺服器端渲染 SSR
SSR(Server-Side Rendering)是在伺服器端生成完整的 HTML 頁面,將已經處理好的頁面回傳給瀏覽器,瀏覽器僅負責頁面的互動功能。
SSR 比起 CSR,使用者能更快看到完整頁面,但由於其處理機制,也對伺服器的負擔較大。
伺服器端渲染對 SEO 極為友善,因為頁面內容已經處理好才發送給使用者,爬蟲能清楚地了解網頁內容。
SSR 的渲染步驟

- 訪客透過瀏覽器發出請求。
- 伺服器接收到該請求。
- 伺服器根據路由動態生成 HTML 頁面,並透過資料庫或 API 取得頁面資料。
- 伺服器將生成的 HTML 頁面返回給瀏覽器。
- 瀏覽器解析 HTML,渲染出完整畫面。
- 訪客看到完整的頁面
React.js 實現伺服器端渲染
my-app/
├─ pages/
│ ├─ index.js # 伺服器端渲染的頁面
pages/index.js
import React from 'react';
const HomePage = ({ post }) => {
return (
<div>
<h1>{post.title}</h1>
<p>{post.body}</p>
</div>
);
};
// 伺服器端渲染函數 (Next.js 特有的)
export async function getServerSideProps() {
const res = await fetch('https://jsonplaceholder.typicode.com/posts/1');
const post = await res.json();
return {
props: { post },
};
}
export default HomePage;
靜態網站生成 SSG
SSG(Static Site Generation)是在構建階段(Build Time)預先產生靜態 HTML 頁面,這些頁面在使用者 request
時直接提供,由於已經是處理好的 HTML,因此渲染速度極快且 SEO 友好。
SSG 渲染步驟
- 在構建時期 (Build Time),開發者運行構建命令,預先生成所有靜態頁面。
- 伺服器或 CDN 儲存這些靜態 HTML 文件。
- 用戶請求頁面時,伺服器直接返回預先生成的靜態 HTML。
- 瀏覽器渲染頁面,React 進行 Hydration 使頁面可交互。
React.js 實現靜態網站生成
my-app/
├─ pages/
│ ├─ index.js
│ ├─ blog/
│ ├─ [id].js # 動態路由靜態生成
核心代碼 pages/blog/[id].js
import React from 'react';
const BlogPost = ({ post }) => {
return (
<div>
<h1>{post.title}</h1>
<p>{post.body}</p>
</div>
);
};
// 在構建時生成靜態頁面
export async function getStaticPaths() {
const res = await fetch('https://jsonplaceholder.typicode.com/posts');
const posts = await res.json();
const paths = posts.map((post) => ({
params: { id: post.id.toString() },
}));
return { paths, fallback: false };
}
// 提供靜態頁面資料
export async function getStaticProps({ params }) {
const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${params.id}`);
const post = await res.json();
return {
props: { post },
};
}
export default BlogPost;
增量靜態重新生成 ISR
ISR(Incremental Static Regeneration)是 SSG 的延伸應用,允許根據設定的時間間隔(revalidate
),在後台自動重新生成靜態頁面,實現靜態頁面的動態更新。
- 渲染時機:構建時生成靜態頁面,根據
revalidate
時間進行再生。 - SEO 支持:非常好。
- 首屏加載速度:快,提供靜態 HTML。
渲染步驟
- 在構建時期預生成初始靜態頁面。
- 用戶請求時,伺服器提供靜態 HTML。
- 當頁面過期(超過設定的
revalidate
時間)時,伺服器在後台重新生成頁面。 - 下一位用戶請求時會看到更新的內容。
// pages/blog/[slug].js
import { useRouter } from 'next/router';
export default function BlogPost({ post }) {
const router = useRouter();
// 顯示載入狀態(可選)
if (router.isFallback) {
return <div>Loading...</div>;
}
return (
<article>
<h1>{post.title}</h1>
<p>{post.content}</p>
</article>
);
}
// 在構建時生成頁面
export async function getStaticPaths() {
const res = await fetch('https://api.example.com/posts');
const posts = await res.json();
const paths = posts.map((post) => ({
params: { slug: post.slug },
}));
return { paths, fallback: 'blocking' };
}
// 提供靜態頁面生成和增量更新邏輯
export async function getStaticProps({ params }) {
const res = await fetch(`https://api.example.com/posts/${params.slug}`);
const post = await res.json();
return {
props: {
post,
},
revalidate: 60, // 每 60 秒重新生成頁面
};
}
不同的頁面渲染方式比較
特性 | CSR | SSR | SSG | ISR |
---|---|---|---|---|
SEO 友善 | 差 | 非常好 | 非常好 | 非常好 |
載入畫面 | 慢 | 中等 | 快 | 快 |
伺服器負載 | 低 | 高 | 最低 | 低 |
更新頻率 | 高 | 即時 | 低 | 中等 |
適用場景 | SPA、 管理系統 | SEO、 動態網站 | Blog、 文檔網站 | 電商、 新聞媒體 |
網站開發人員能根據以上的表格中的優缺點與應用情境,決定合適的渲染方式。React 可以使用 Next.js 提供混合渲染策略,達到最佳性能和 SEO 效果!
透過動態渲染改善 CSR 頁面
動態渲染(Dynamic Rendering)是一種針對搜尋引擎爬蟲與訪客瀏覽器提供不同內容的技術。這種方法的主要目的是改善單頁應用(SPA)或使用 CSR 網站的 SEO 表現,確保搜尋引擎能夠正確檢索和索引網站內容。

在動態渲染的架構下:
- 如果
request
來自 Googlebot,伺服器會response
預先渲染(Prerender)的靜態 HTML,以確保爬蟲能看到完整的頁面,以達到 SEO 友善。 - 如果
request
來自一般瀏覽器,則正常執行 CSR,透過 JavaScript 載入並渲染頁面。
下面是常見的動態渲染解決方案,可以導入在前端框架開發的 CSR 網頁上:
- Prerender.io:基於 Headless Chrome 的預渲染解決方案,它會在伺服器上自行透過瀏覽器將 JavaScript 渲染後的 HTML 儲存起來,然後根據請求來源提供對應的內容。
- Rendertron:Google 提供的開源解決方案,與 Prerender.io 類似,它也會使用 Headless Chrome 預渲染 JavaScript,然後為爬蟲提供靜態 HTML。
References
Dynamic Rendering as a workaround | Google for Developers
Dynamic Rendering with Rendertron | Google for Developers
Rendering on the Web | Articles | web.dev
Data Fetching: Incremental Static Regeneration (ISR) | Next.js