深入理解 Hydration:現代前端框架的「必要之惡」?

6 分鐘

1. SSR 的美好與煩惱

服務端渲染 (SSR) 極大地改善了 Web 應用程式的「首屏載入速度」 (FCP)。瀏覽器直接接收到完整的 HTML 內容並立刻渲染,使用者能很快看到頁面內容,這對 SEO 和使用者感知都非常友善。

但此時的頁面只是一個「靜態的空殼」。雖然看起來已經載入完畢,但頁面上的按鈕點擊、輸入框互動都毫無反應。為了讓這個靜態頁面「活」過來,我們需要一個過程,這個過程就是 Hydration(注水/啟用)。

2. 什麼是 Hydration?

Hydration 是指客戶端的 JavaScript 框架「接管」由服務端渲染的靜態 HTML 的過程。

這個過程大致如下:

  1. 瀏覽器下載並執行頁面所需的 JavaScript 套件(例如 React、Vue 的執行階段和業務程式碼)。
  2. 框架在記憶體中重新建構元件樹。
  3. 框架遍歷服務端渲染的 DOM,並將事件監聽器(如 onClick)附加到對應的 DOM 節點上。
  4. 框架確保客戶端的元件狀態與服務端渲染時的狀態一致。

完成之後,頁面才真正變得可互動。可以把 Hydration 想像成:你收到一個已經拼好的樂高模型(HTML),但為了讓模型的某個元件能動,你必須把整個模型的拼裝說明書(JS)從頭到尾讀一遍,並檢查一遍所有積木的位置,然後才給那個元件裝上電池(附加事件監聽器)。

3. Hydration 的問題:「非互動的互動介面」

Hydration 解決了 SSR 頁面無法互動的問題,但它自身也帶來了新的效能瓶頸,即所謂的 「非互動幽谷」 (Uncanny Valley)「注水延遲」 (Hydration Gap)

這個問題指的是從使用者看到頁面內容 (FCP) 到頁面可以真正回應使用者互動 (TTI) 之間存在一個時間差。在這個時間差內,頁面看起來是可用的,但實際上是「假死」狀態。

造成這個問題的原因是:

  • JS 下載和執行阻塞: 瀏覽器必須下載、解析並執行大量的 JavaScript 程式碼,才能開始 Hydration 過程。
  • 昂貴的啟動成本: 框架需要在客戶端執行大量工作來重新建構元件樹和附加事件監聽器,即使頁面上 90% 的內容都是非互動的靜態內容。

4. Hydration 的最佳化與替代方案

為了解決 Hydration 的效能問題,社群探索出了多種更先進的模式。

a. 局部注水 (Partial Hydration)

Astro 框架推廣的 島嶼架構 (Islands Architecture) 是局部注水的典型實作。其核心思想是:預設情況下,所有元件都只輸出純靜態 HTML(零 JS)。對於需要互動的元件,你可以將其明確標記為一個「島嶼」。

建置時,Astro 只會為這些「島嶼」元件打包並傳送 JavaScript。這樣,瀏覽器只需對頁面上的幾個孤立部分進行 Hydration,而不是整個頁面,極大地減少了啟動時需要載入和執行的 JS 量。

b. 漸進式注水 (Progressive Hydration)

這是一種更細粒度的最佳化策略,它按照一定的優先順序來 Hydrate 元件。例如,可以優先 Hydrate 視口內或使用者即將互動的元件,而延遲處理頁面底部的、非關鍵的元件。

c. 可恢復性 (Resumability)

Qwik 框架提出了一個革命性的概念——Resumability,旨在完全消滅 Hydration。

它的運作方式是:

  1. 序列化: 在服務端,Qwik 將應用程式的所有狀態、元件關係、事件監聽器等資訊全部序列化,並嵌入到 HTML 中。
  2. 恢復: 在客戶端,Qwik 的極小執行階段(約 1KB)不需要在啟動時重新建構元件樹或附加所有事件。它透過一個全域的事件監聽器,可以精確地知道當使用者點擊某個按鈕時,應該去下載並執行哪一小塊程式碼。

Qwik 的目標是實現 即時互動 (Instant-on)。它不是「重新執行」一遍服務端的工作,而是從服務端停止的地方「恢復」執行。

結論

Hydration 是連接服務端渲染和客戶端互動的橋樑,但在傳統實作中,它是一個昂貴且可能損害使用者體驗的過程。現代前端框架正在透過局部注水(Astro)和可恢復性(Qwik)等創新模式,努力擺脫 Hydration 這個「必要之惡」,向著更極致的效能和更快的互動速度邁進。