雅寶社區 · 頂客論壇 (AHPAL.COM)

2026 年 Next.js 14 App Router 實戰:從入門到 Server Components

發表時間:2026 年 08 月 09 日 | 更新日期:2026 年 08 月 09 日 | 編輯:雅寶社區編輯團隊

嗨,雅寶社區的朋友們!不知不覺我們已經來到 2026 年,前端框架的戰國時代依然如火如荼地進行著。在眾多選擇中,Next.js 憑藉其完整的全端框架特性與極佳的開發者體驗,依然是許多團隊與獨立開發者的首選。而其中,App RouterServer Components 更是徹底改變了我們思考 React 應用程式的方式。如果你正在尋找一份從零開始、且能深入理解核心概念的實戰教學,那麼這篇文章就是為你準備的。我們將跳過紛雜的理論,直接帶你動手實作,並解釋每個環節的「為什麼」。準備好了嗎?讓我們一起進入 Next.js 14 的世界。

modern%20workspace%20with%20laptop%2C%20smartphone...

為什麼選擇 Next.js 14 與 App Router?

在 2026 年回頭看,Next.js 14 無疑是奠定未來數年 React 架構的重要基石。雖然新版本不斷推出,但 14 的穩定性、豐富的固化 API 與廣大的社群支援,使它成為眾多大型專案的上線標準。更重要的是,它讓我們能以更直覺、更具效能的方式建構應用程式,這一切的核心就是 App Router

Pages Router 到 App Router:一場思維革命

過去我們習慣了 Pages Router 的檔案系統路由,每個資料夾與檔案對應一個 URL。然而,這種方式在面對複雜的巢狀佈局(Nested Layout)時,往往需要透過 _app.tsx_document.tsx 手動拼湊,導致程式碼混亂且難以維護。App Router 則引入了更優雅的 佈局(Layout) 模型,讓共享的 UI(如導覽列、頁尾)能夠在某個路由片段中獨立定義,並自動套用至其下所有子路由。這不僅大幅降低了重複程式碼,更使得頁面之間的狀態切換可以更流暢,因為佈局可以保持掛載狀態,不會因為路由改變而重新渲染。

此外,App Router 的檔案命名約定(如 loading.tsxerror.tsxnot-found.tsx)讓開發者可以非常直覺地覆寫特定路由的 UI 狀態,這在過去需要透過複雜的條件判斷或自訂 Error Boundary 才能實現。這些改進都歸功於一個更深層的架構調整:將伺服器與客戶端的職責明確分離

Server Components:全新的效能武器

Next.js 14 徹底擁抱了 React 的 Server Components(簡稱 RSC)。這項技術最核心的價值在於:讓元件在伺服器上執行,直接讀取後端資源(如資料庫、檔案系統),產生的 HTML 再傳送給客戶端。這意味著,我們不需要為了取得資料而撰寫大量的 useEffect + fetch 等待過程,也不需要將所有資料請求封裝在 API 路由中(當然,API 路由依然有其用武之地)。部分原本在瀏覽器上必須下載的 JavaScript 程式碼,現在可以在伺服器端執行完畢,直接將結果以序列化形式傳遞,大幅減少客戶端套件體積與渲染等待時間。

想像一個部落格的文章頁面:過去你可能要先載入整個頁面,然後再發一個 AJAX 請求取得文章內容。現在,透過 Server Component,你可以在伺服器端撰寫一個 async function,直接對資料庫查詢,將查詢結果渲染為元素,並立即傳送給瀏覽器。這不僅提升了首屏速度,也減輕了客戶端的運算負擔,更讓 SEO 變得更加直接——搜尋引擎爬蟲收到的 HTML 就是完整內容,不需要等待 JavaScript 執行。這就是 Next.js 14 想要帶給我們的體驗。

環境建置與專案初始化

在開始實作之前,我們需要準備好開發環境。首先,確認你的 Node.js 版本大於等於 18.17(建議使用 20 以上)。接著,我們透過 create-next-app 這個官方的初始化指令來建立專案。

npx create-next-app@latest my-community-app

yarn create next-app my-community-app

pnpm create next-app my-community-app

在互動式對話中,記得選擇以下選項:

  • TypeScript:選擇 Yes,可讓你的程式碼更具型別安全。
  • ESLint:選擇 Yes,檢查程式碼風格。
  • Tailwind CSS:可根據偏好選擇,即使在 2026 年 Tailwind 依然是高效的樣式方案。
  • App Router:務必選擇 Yes
  • Import alias:建議使用預設的 @/*,方便路徑引用。
  • React Compiler:如果該選項存在,可視為實驗性功能,後續再說明。
  • 專案初始化完成後,進入專案目錄並啟動開發伺服器:

    cd my-community-app

    npm run dev

    打開 http://localhost:3000,你應該會看到 Next.js 的歡迎頁面。現在,讓我們看看初始的專案結構。

    my-community-app/

    ├── app/

    │ ├── favicon.ico

    │ ├── globals.css

    │ ├── layout.tsx

    │ └── page.tsx

    ├── public/

    ├── .eslintrc.json

    ├── next.config.mjs

    ├── package.json

    └── tsconfig.json

    在 App Router 的架構下,app 目錄是我們的核心。資料夾的路徑對應 URL,而特定的檔案名稱如 page.tsxlayout.tsx 負責渲染不同的 UI。接下來,我們將深入探索這些檔案的角色。

    深入理解 App Router 的核心概念

    要熟悉 App Router,不能只是會操作檔案,而是要理解它背後的設計邏輯。這裡我們將拆解幾個最基礎且最重要的檔案與約定。

    Layout (佈局) 與 Template

    layout.tsx 是 App Router 最重要的檔案之一。它接收一個 children prop,用來渲染巢狀的子頁面或子佈局。Layout 的主要特性是:它在導覽時會保持狀態,不會因為切換路由而重新掛載(除非整個佈局本身被重新渲染)。這使得側邊欄、導覽列等共享元件可以保有本地的狀態,例如使用者捲動位置,或是表單輸入的暫存內容。

    一個根佈局(app/layout.tsx)必須存在,且必須包含 htmlbody 標籤。接下來,你可以透過資料夾嵌套的方式建立子佈局,例如在 app/blog/layout.tsx 中設定專屬於部落格區塊的頁首。

    // app/layout.tsx

    import type { Metadata } from 'next';

    import './globals.css';

    export const metadata: Metadata = {

    title: '我的社群論壇',

    description: '一個以 Next.js 14 打造的互動空間',

    };

    export default function RootLayout({

    children,

    }: Readonly) {

    return (

    <html lang="zh-TW">

    <body className="bg-gray-50 min-h-screen">

    <header className="bg-gray-800 text-white p-4">

    <nav>導覽列</nav>

    </header>

    <main>{children}</main>

    <footer className="bg-gray-200 p-4 text-center">

    版權所有 © 2026 雅寶社群

    </footer>

    </body>

    </html>

    );

    template.tsxlayout.tsx 不同的是,template 會在每次導覽時重新建立一個新的實例。如果你有某些 UI 元件需要在使用者每次訪問新的路由時重置狀態(例如一組每日更新的精選文章),那麼 template 就是正確選擇。

    Pages (頁面) 與 Dynamic Routes (動態路由)

    page.tsx 負責定義一個路由的最終 UI。你可以在任何資料夾中建立 page.tsx,它必須導出一個 React 元件。例如,`app/about/page.tsx` 對應 `/about`。

    對於動態路由,我們只要在資料夾名稱中使用方括號,例如 app/posts/[id]/page.tsx 就會匹配 `/posts/1`、`/posts/abc` 等路徑。在元件中,我們透過 params prop 取得動態段的值(在 2026 年,我們可以使用 Promise 型別來處理非同步的參數,這其實是 Next.js 15 的特性,但 14 也支援過渡期的處理方式,建議採用新版官方推薦的 Promise 風格)。

    // app/posts/[id]/page.tsx

    type Params = { params: { id: string } };

    // Next.js 14 中 params 為同步物件,但可以這樣寫

    export default async function PostPage({ params }: Params) {

    const post = await getPost(params.id);

    return (

    <article>

    <h1>{post.title}</h1>

    <p>{post.content}</p>

    </article>

    );

    當你需要產生靜態參數時,可以使用 generateStaticParams 函式。這告訴 Next.js 在建置期間預先產生哪些路徑的 HTML。

    export async function generateStaticParams() {

    const posts = await fetch('https://jsonplaceholder.typicode.com/posts').then((res) => res.json());

    return posts.map((post: { id: number }) => ({ id: String(post.id) }));

    Loading UI 與 Error Handling

    App Router 支援特殊的 loading.tsxerror.tsx 檔案。當網頁正在載入某個 Client Component 或正進行資料請求時,瀏覽器會立即顯示 loading.tsx 中的內容。你可以設計一個精美的、帶有動畫的骨架屏,大幅改善使用者體驗,而不需要自行撰寫「載入中」的狀態邏輯。

    // app/loading.tsx

    export default function Loading() {

    return <div>正在載入文章,請稍候…</div>;

    `error.tsx` 則是一個錯誤邊界(Error Boundary)。當子路由拋出未捕獲的例外時,就會顯示此檔案內的 UI。這個元件必須是 Client Component,並導出一個帶有 errorreset 屬性的元件。reset 是一個函式,可以嘗試重新渲染路由。

    // app/error.tsx

    'use client';

    export default function Error({ error, reset }: { error: Error; reset: () => void }) {

    return (

    <div>

    <h2>發生錯誤!</h2>

    <p>{error.message}</p>

    <button onClick={reset}>重新試試</button>

    </div>

    );

    Server Components 實戰

    現在我們踏入了 Next.js 14 的核心精髓:Server Components。預設情況下,在 App Router 中定義的所有元件都是 Server Components,除非你在檔案頂部加上 'use client' 指令,這樣它才會成為 Client Component。理解何時使用哪一種,正是效能優化的關鍵。

    建立一個顯示使用者資料的 Server Component

    讓我們建立一個實際的範例:一個顯示目前線上使用者的元件。設想我們的論壇需要展示一份活躍使用者列表。過去我們可能需要先建立一個 API,然後在 Client Component 中使用 useEffect 去抓取。現在,在 Server Component 中,我們可以直接在元件內對資料源進行查詢(這裡我們模擬一個非同步函式)。

    // app/components/ActiveUsers.tsx (Server Component)

    interface User {

    id: number;

    name: string;

    avatar?: string;

    async function getActiveUsers(): Promise<User[]> {

    // 假設這是從資料庫或後端服務取得的資料

    const res = await fetch('https://api.example.com/users/active', { next: { revalidate: 60 } });

    if (!res.ok) {

    // 這裡可以拋出錯誤交給 error.tsx 處理

    throw new Error('無法取得活躍使用者');

    return res.json();

    export default async function ActiveUsers() {

    const users = await getActiveUsers();

    return (

    <div className="bg-white shadow rounded-lg p-6">

    <h2 className="text-xl font-semibold mb-4">目前線上使用者</h2>

    <ul className="divide-y divide-gray-200">

    {users.map((user) => (

    <li key={user.id} className="py-2 flex items-center space-x-3">

    <span className="w-8 h-8 rounded-full bg-indigo-500 flex items-center justify-center text-white">

    </span>

    <span className="text-gray-700">{user.name}</span>

    </li>

    </ul>

    </div>

    );

    在 2026 年,我們可以更進階地使用 cache (unstable_cache) 或 Server Actions 的延伸功能來最佳化資料請求。但從簡單開始,我們就能看到 Server Component 的強大之處:它直接將資料獲取與 UI 渲染結合為一體,減少了大量樣板程式碼,且透過 next: { revalidate: 60 } 我們可以精準控制資料的快取時間(ISR),這在過去需要額外設定。

    Client Components 與 Server Components 的組合

    不是所有元件都適合在伺服器端執行。當你需要使用 useState、useEffect、onClick 事件處理、或使用只能瀏覽器存取的 API(如 window、localStorage)時,你必須將這些元件標記為 Client Component。在 Next.js 14 中,最佳的實踐是建立一個「邊界」,將 Server Components 作為資料層與巢狀的 Client Components 串接起來。

    想像一個購物車畫面:顯示購物車內的商品列表(適合 Server Component,直接查詢資料庫),但每個商品項目的數量調整按鈕(需要 onClick)則必須是 Client Component。

    // app/cart/CartItem.tsx

    'use client';

    而在上游的 Server Component 中,我們可以將資料作為 props 傳遞給這些 Client Components,無需再自己抓取資料。這形成了一個既高效又清楚的資料流。

    // app/cart/page.tsx

    import CartItem from './CartItem';

    export default async function CartPage() {

    // 直接查詢購物車內容

    const cartItems = await getCartItems();

    return (

    <div>

    <h1>你的購物車</h1>

    {cartItems.map((item) => (

    <CartItem key={item.id} id={item.id} initialQuantity={item.quantity} />

    </div>

    );

    這種組合模式,我們稱之為「Server-Driven UI」:伺服器提供最終狀態的資料與結構,客戶端元件只負責互動與動態視覺。這不僅提升了效能,更讓應用程式邏輯更集中、更易於測試。

    進階應用與最佳實踐

    在掌握了基本概念後,我們來探討一些 2026 年實際專案中不可或缺的進階主題,這些技術深深植根於 App Router 的生態系,也是我們在頂客論壇中頻繁討論的焦點。

    Powerful Data Fetching:Server Actions 的革命

    App Router 的一大亮點是引入了 Server Actions。這項功能允許我們從 Client Component 中直接呼叫伺服器端函式,而不必手動建立 API 路由。使用方式非常直接:在 client component 內,你可以透過 useTransition 或直接使用 formaction prop 來呼叫伺服器函式。

    // app/components/MessageForm.tsx

    'use client';

    // app/actions.ts (Server Action)

    'use server';

    export async function sendMessage(formData: FormData, roomId: string) {

    const content = formData.get('content');

    if (!content || typeof content !== 'string') {

    throw new Error('訊息內容不可為空');

    // 在伺服器端儲存訊息

    await db.message.create({

    data: {

    roomId,

    content,

    userId: currentUserId(), // 從 session 取得

    },

    });

    // 可以 revalidate 相關路徑

    revalidatePath(`/rooms/${roomId}`);

    Server Actions 極大地簡化了資料變更的流程,同時維持了安全性(程式碼永遠不會被送到客戶端)。在 2026 年,這已經是建構互動式表單與聊天室的標準方式。搭配漸進增強(Progressive Enhancement),即使 JavaScript 尚未載入,表單也能運作。

    Middleware 與路由守衛

    在 App Router 中,Middleware(中介軟體)可以在請求到達頁面或邏輯之前執行。這對驗證使用者身份、重定向、設定 Cookie 與 A/B 測試非常有用。你可以建立一個 middleware.ts 檔案放在專案根目錄(與 src 或 app 同層級)。

    // middleware.ts

    return NextResponse.next();

    // 指定應執行的路徑

    export const config = {

    matcher: ['/dashboard/:path*', '/admin/:path*'],

    };

    這個模式在論壇系統中非常實用,例如確保只有版主能訪問管理後台,或根據使用者角色顯示不同版面。切記,Middleware 在 Edge Runtime 中執行,因此不適合使用 Node.js 原生套件,應保持輕量。

    SEO 優化技巧

    由於 App Router 的頁面預設在伺服器端渲染,因此 SEO 的基礎已經非常牢固。但我們可以透過 generateMetadata 來動態生成 meta 標籤,這比傳統在 _document 中靜態設定要強大得多。

    // app/posts/[id]/page.tsx

    import type { Metadata } from 'next';

    async function getPost(id: string) {

    // 取得文章資料

    return fetch(`https://api.example.com/posts/${id}`).then((res) => res.json());

    export async function generateMetadata({ params }: { params: { id: string } }): Promise<Metadata> {

    const post = await getPost(params.id);

    此外,你可以為特定頁面建立 sitemap.tsrobots.ts,讓搜尋引擎爬蟲更有效率地索引你的內容。這些都是 Neat.js 14 中內建支援的,只要在 app 資料夾下建立這些檔案即可。在 2026 年,搜尋引擎的 SEO 評估指標更加重視 Core Web Vitals,而 Server Components 與 Streaming 帶來的效能提升,正好完美對應這些需求。

    從 2026 年展望:未來與社群力量

    在我們完成這個基礎到進階的旅程時,不妨回顧一下,Next.js 14 所建立的這個資料處理模式,如何深刻影響了整個前端生態。直到 2026 年的今日,我們依然可以看到大量基於 App Router 的開源專案與企業應用,顯示其生命週期的穩定與可持續性。透過本篇文章實際操作與理解,相信你已經具備建構一個高效能、高可維護性的現代化 Web 應用的能力。

    當然,技術日新月異,此刻的 Next.js 可能已有了更新的版本(例如 15、16),但核心思想——以伺服器為優先、資料與 UI 共置、透過框架約定解決常見難題——依然主導著框架的演進。學習 App Router,不只是學習一個工具,更是建立一種新的思考方式。你現在可以在雅寶社區與頂客論壇中,分享你的作品與心得,與其他同樣熱愛 3C 與科技的朋友們交流,我們都很期待看到你的獨特見解。

    結語:將知識轉化為作品

    本篇文章從環境建置、核心概念、Server Components 到進階的 Server Actions 與 Middleware,提供了一個完整的實作路徑。我們未過度深入每一個小細節,而是專注於最重要且最常被應用的部分。你現在可以試著將這個技能應用到自己的專案:也許是一個個人部落格、一個小型電商網站、或是一個類似的論壇。透過動手實作,以及查閱官方文件並參與社群討論(例如雅寶社區的技術版塊),你一定能精通 Next.js 14。

    記住,閱讀是最好的學習,但撰寫程式碼才能獲得真正的成長。現在就打開你的終端機,建立你的第一個 App Router 專案吧!當你遇到問題時,別忘了在頂客論壇中發問,這裡總有熱心的專家願意伸出援手。衷心期待看到你的下一件偉大作品。

    本文由雅寶社區 · 頂客論壇編輯群撰寫,歡迎分享轉載,但請保留原文連結並註明出處。如有任何 Next.js 相關疑問,歡迎在下方留言討論。

    💬 留言討論

    歡迎在下方留言,分享您的想法、心得或疑問。所有留言都會透過 GitHub 帳號 進行驗證。

    🏠 返回首頁