Next.js Server Components 與 Client Components

Next.js 的 App Router 建立在 React 的最新特性上:伺服器元件 (Server Components)客戶端元件 (Client Components)。理解這兩者的區別與合作方式,是開發高效能應用的不二法門。

伺服器元件 (Server Components)

在 Next.js 中,app 目錄下的所有元件預設都是伺服器元件。它們直接在伺服器端執行並渲染成 HTML,然後發送到瀏覽器。

優點:

  • 減少 JS 體積:伺服器端的套件(如 fs, sql)不會被下載到瀏覽器,這讓用戶端載入變極快。
  • SEO 友善:搜尋引擎爬蟲可以直接讀取完整的 HTML。
  • 安全性:敏感資訊(如 API Keys)保存在伺服器端,不會外流。
  • 直接讀取資料庫:你可以直接在元件內撰寫 async/await 來抓取數據。
// 預設就是 Server Component
async function getPosts() {
  const res = await fetch('https://api.example.com/posts');
  return res.json();
}

export default async function BlogPage() {
  const posts = await getPosts(); // 在伺服器端執行

  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  );
}

客戶端元件 (Client Components)

如果你需要與使用者進行互動(如點擊事件、計時器、使用 React Hook 等),你就必須將元件標註為客戶端元件。

如何宣告?

在檔案的最頂端加上 'use client'; 指令。

'use client'; // 標註為 Client Component

import { useState } from 'react';

export default function Counter() {
  const [count, setCount] = useState(0);

  return <button onClick={() => setCount(count + 1)}>點擊次數:{count}</button>;
}

何時使用哪種組件?

需求Server ComponentClient Component
擷取數據 (Fetch Data)✅ (推薦)
存取後端資源 (直接讀 DB)
點擊事件、狀態操作 (onClick, useState)
使用瀏覽器 API (window, localStorage)
減少用戶端 JavaScript

組合模式:最佳實踐

  1. 下移 Client Components:盡量保持 Server Components 的層級,只在需要互動的小區塊使用 'use client'
  2. 傳入 Props 而非 Import:如果你需要在 Client Component 裡面包含一個 Server Component,請透過 children 傳入。
// ❌ 錯誤:在 Client Component 中 import Server Component 會使其變成 Client 組件
// ✅ 正確:
export default function ParentServerComponent() {
  return (
    <MyClientLayout>
      <ServerSidePosts /> {/* 作為 children 傳入 */}
    </MyClientLayout>
  );
}

在 React 的架構中,Client Component 位於渲染樹(Render Tree)的葉子節點或較低層級。當你直接 import 一個 Server Component 到 Client Component 時,React 為了確保瀏覽器能夠執行這些程式碼,會將該元件及其所有依賴項一起打包(Bundle)到客戶端。

這時,該元件會失去 Server Component 的特權(例如:直接存取資料庫、使用伺服器端環境變數等),並變成一個普通的 Client Component 在瀏覽器執行。

小結

Next.js 讓你在同一個專案中混合這兩種模式。口訣是:預設使用 Server Components,直到你需要使用者互動時才下移至 Client Components。