Next.js App Router :什麼時候適合使用 Server Components 或 Client Components?
在 Next.js App Router 中,Server Components 和 Client Components 的選擇是根據你的應用需求和功能來決定的。讓我詳細解釋這兩者的適用情境:
Server Components(預設)
適合使用的情境:
-
資料獲取
-
需要從資料庫或 API 獲取資料
-
處理敏感資訊(API 金鑰、資料庫連線等)
-
SEO 需要的內容渲染
-
-
靜態內容顯示
-
文章內容、產品列表
-
導覽列、頁腳等不需互動的元件
-
純展示性的 UI 元件
-
-
伺服器端邏輯
-
資料處理和轉換
-
身份驗證檢查
-
路由保護
-
範例:
// app/products/page.js (Server Component)
export default async function ProductsPage() {
// 在伺服器端獲取資料
const products = await fetch("https://api.example.com/products");
const data = await products.json();
return (
<div>
<h1>產品列表</h1>
{data.map((product) => (
<div key={product.id}>
<h2>{product.name}</h2>
<p>{product.price}</p>
</div>
))}
</div>
);
}
Client Components
適合使用的情境:
-
使用者互動
-
按鈕點擊、表單提交
-
滑鼠懸停效果
-
拖拉功能
-
-
瀏覽器 API
-
localStorage、sessionStorage
-
geolocation 定位
-
檔案上傳
-
-
React Hooks
-
useState、useEffect
-
useRouter(來自 next/navigation)
-
自定義 hooks
-
-
即時更新
-
計時器、倒數功能
-
即時聊天
-
動態搜尋
-
範例:
// components/SearchBox.js (Client Component)
"use client"; // 必須加上這行
import { useState } from "react";
export default function SearchBox() {
const [query, setQuery] = useState("");
const handleSearch = () => {
console.log("搜尋:", query);
// 處理搜尋邏輯
};
return (
<div>
<input
type="text"
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="請輸入關鍵字..."
/>
<button onClick={handleSearch}>搜尋</button>
</div>
);
}
混合使用策略
你可以在 Server Component 中嵌入 Client Component:
// app/page.js (Server Component)
import SearchBox from "@/components/SearchBox"; // Client Component
export default async function HomePage() {
// 伺服器端獲取資料
const posts = await getPosts();
return (
<div>
<h1>部落格首頁</h1>
{/* Client Component 用於互動 */}
<SearchBox />
{/* Server Component 用於顯示內容 */}
<div>
{posts.map((post) => (
<article key={post.id}>
<h2>{post.title}</h2>
<p>{post.excerpt}</p>
</article>
))}
</div>
</div>
);
}
選擇建議
優先使用 Server Components:
-
更好的效能(較小的 bundle 大小)
-
更好的 SEO
-
更安全(敏感邏輯在伺服器端)
只有在需要互動功能時才使用 Client Components:
-
具體需要使用者互動
-
需要瀏覽器 API
-
需要 React Hooks
記住,你可以從小範圍開始使用 Client Components,不需要整個頁面都設為 Client Component。這樣可以獲得兩者的優點!