iT邦幫忙

2026 iThome 鐵人賽

DAY 25
0
JavaScript

React 觀念架構:從js 基礎到Hook 底層邏輯 系列 第 25 篇

Day 25 SSR / SSG / ISR 演進史:hydrate (Hydration) 水合是什麼?

  • 分享至 

  • xImage
  •  

今天我們要將視角從「純前端 CSR (Client-Side Rendering)」拉高到伺服器端與渲染範式的演進史,並解答前端最常聽到卻也最抽象的概念:Hydration(水合)。

一、 渲染範式的演進史:從 CSR 到 SSR、SSG、ISR

前端渲染架構的演進,本質上是在「SEO / 首屏速度 (FCP)」 與 「伺服器負擔 / 內容即時性」 之間尋找最佳平衡點:

[CSR] ──► [SSR] ──► [SSG] ──► [ISR]
傳統 CSR:空白 HTML,等待 JS 下載繪製
SSR:伺服器即時渲染 HTML,SEO 友善但伺服器負擔高
SSG:建置階段 (Build-time) 預先產生 HTML,速度極快但無法即時更新
ISR:結合兩者,靜態頁面支援背景按需重新產生 (Revalidate)

https://ithelp.ithome.com.tw/upload/images/20261009/201785169AnDXCSLoI.png

二、 到底什麼是 Hydration(水合 / 注入水份)?

在 SSR 或 SSG 的流程中,伺服器會先傳送一份已經包含完整文字與 DOM 結構的 HTML 給瀏覽器。使用者此時能「看到」畫面(首屏渲染快),但此時的 HTML 只是靜態的乾涸骨架,無法進行點擊、輸入或觸發任何狀態變更。

水合的三步驟:

  1. 伺服器端 (Server):執行組件渲染,輸出 HTML 字串與 state 快照傳給瀏覽器。

  2. 瀏覽器下載 JS (Client):下載並解析 React JS Bundle。

  3. Hydrate 過程:React 不重新創建 DOM 節點,而是遍歷現有的 HTML DOM 樹,將 Event Listeners(如 onClick)附著上去,並綁定對應的 Fiber 節點與 State。

import { hydrateRoot } from 'react-dom/client';

// 將 React 的交互邏輯「水合」至伺服器已渲染好的 HTML 容器中
hydrateRoot(document.getElementById('root'), <App />);

三、 水合不一致 (Hydration Mismatch / Mismatch Error)

這是開發 SSR/SSG 時最常發生的警告。當伺服器渲染出的 HTML 結構與客戶端初次 Re-render 的 Virtual DOM 結構不一致時,React 就會拋出語法錯誤。

常見引發原因:

  1. 使用了特定於瀏覽器的動態數據:例如在組件中直接寫死 window.innerWidth、localStorage 或 new Date().toLocaleTimeString()(伺服器與客戶端時間不同步)。

  2. 不合法的 HTML 嵌套結構:例如在 <p> 標籤內包裹<div>,導致瀏覽器原生的 HTML Parser 自動做修正,破壞了原本的 DOM 結構。

// 錯誤範例:伺服器端輸出 Time A,客戶端水合時變成 Time B
function Clock() {
  return <span>現在時間:{new Date().toLocaleTimeString()}</span>;
}

// 解法:確保水合階段與伺服器一致,掛載完成後 (useEffect) 再更新為客戶端時間
function Clock() {
  const [time, setTime] = useState(null);
  
  useEffect(() => {
    setTime(new Date().toLocaleTimeString());
  }, []);

  return <span>現在時間:{time ?? '載入中...'}</span>;
}

上一篇
Day 24 Diffing 演算法拆解:單節點與多節點 Diff 的啟發式策略
系列文
React 觀念架構:從js 基礎到Hook 底層邏輯 共 25 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言