在 App Router 中,所有元件預設都是 Server Components。它們只在伺服器端執行,不會將任何 JavaScript 程式碼打包傳送到使用者的瀏覽器。
lodash、date-fns 或大型 Markdown 解析器等重型套件,如果只在 Server Component 使用,它們的程式碼永遠不會被下載到客戶端,大幅縮減了 JavaScript 包體積。當元件需要依賴瀏覽器專屬環境或動態狀態時,必須在檔案最頂端加上
"use client"指令。這並非代表該元件「只能在瀏覽器渲染」,而是建立了一個「模組邊界(Boundary)」。
"use client":
useState、useEffect、useReducer、useTransition。onClick、onChange、onSubmit 等。window、document、localStorage、navigator。"use client" 的元件及其引用的所有子元件,都會被打包並下載到瀏覽器中執行(SSR 初始化後進行 Hydration 水合)。實務開發中最有效率的設計模式,是讓 Server Component 擔任父層,而 Client Component 擔任子層:
await listItems()),並將靜態資料透過 Props 往下傳遞。這確保了首屏載入時,資料已經內嵌在 HTML 中,對 SEO 極度友善。ItemCard 裡的勾選、刪除、useTransition 載入狀態)。這種設計兼顧了 Server-side 的極速載入 與 Client-side 的豐富互動,是現代全端框架的最佳實踐。
當伺服器收到網頁請求時,Server Component 並不會直接轉成普通的 HTML 字串,而是會被編譯並序列化成一種稱為 RSC Payload 的特殊資料結構。其包含:
1. 伺服器端元件執行後的渲染結果。
2. 預留給 Client Component(例如 ItemCard)的佔位符(Slots)與對應的 JS 檔案參照路徑。
3. 由 Server 端傳遞給 Client 端的 Props 資料(例如從資料庫撈出來的 item 物件)。
瀏覽器首次載入時,伺服器會結合 HTML 與 RSC Payload 一起送達。瀏覽器收到後,會用 HTML 快速拼出首屏畫面,然後利用 RSC Payload 在背景將 Client Component「水合(Hydration)」並點亮互動功能。
當使用者輸入網址,伺服器只是把排版好的 HTML 傳給瀏覽器。使用者雖然瞬間就能看到畫面(First Contentful Paint 很高),但這只是一張「沒有靈魂的精美海報」,你點擊按鈕、輸入框,完全沒反應,因為 JavaScript 還沒執行。
而 Hydration 就像是把脫水食品加水還原,當瀏覽器接著下載 JavaScript 檔案時,React 會把對應的事件監聽器(如 onClick、useState 等狀態)重新綁定到對應的 DOM 元素上。
這個「把事件和狀態綁上去」的過程,就是 Hydration。完成之後,網頁就從「靜態圖片」變成「真正的互動應用」了。