第二章:Next.js App Router 實戰 - 現代化前端架構與極致 SEO 最佳化
這幾年,只要你關注網頁開發趨勢,你一定會聽到全世界都在瘋 Next.js。 如果你以前寫過傳統的 React (例如使用 Create React App 或是 Vite),你一定會覺得 React 很好寫、互動很順暢。 但當你辛辛苦苦把做好的網站部署到網路上,過了一個月,你會發現一個致命的商業問題:你在 Google 完全搜尋不到你的網站內容。
這就是傳統 SPA (Single Page Application,單頁應用程式) 的硬傷。因為 SPA 送給瀏覽器的 HTML 基本上是一片空白(只有一個 <div id="root"></div>),所有的精彩內容都是等使用者的瀏覽器下載完龐大的 JavaScript 之後,才用程式在客戶端「畫」上去的。
對於一個需要靠 SEO (搜尋引擎最佳化) 帶來免費自然流量的「知識付費平台」或是「電商網站」來說,這是毀滅性的打擊。Google 爬蟲一進來,看到白紙一張,就頭也不回地走了。
為了解決這個痛點,Next.js 誕生了。而在 Next.js 13 之後推出的 App Router,更是將前端開發帶入了一個全新的紀元。
🎯 本章目標
- 深入理解 Server Components 與 Client Components 的商業價值。
- 掌握 App Router 資料夾層級的直覺路由設計。
- 實作動態路由 (Dynamic Routes),讓系統能自動承載一萬堂課程。
- 學習 Metadata API,打造滿分的 SEO 分享體驗。
🚀 Server Components vs Client Components
在我們這套系統的原始碼中,你會頻繁地看到有些檔案最上方寫著 "use client";,而有些什麼都沒寫。這是 App Router 最核心顛覆性的概念:
1. Server Components (伺服器元件:預設值)
在 App Router 中,如果你不特別宣告,所有的 Component 預設都是 Server Components。 這意味著這些元件會在伺服器端 (Server) 就先執行完畢,把資料抓好、把 React 程式碼運算成乾淨純粹的 HTML 後,再把這個 HTML 傳給使用者的瀏覽器。
🏆 商業級優點:
- 極致的 SEO:爬蟲一進來就看到完整的文章內容,立刻收錄。
- 零 JavaScript Bundle:因為在伺服器就渲染完了,這些元件的 JavaScript 程式碼「根本不會傳到使用者的手機裡」。使用者的手機不用花算力去解析 JS,網頁載入速度就像閃電一樣快!這會大幅降低跳出率 (Bounce Rate)。
- 絕對安全的資料獲取:你可以直接在元件裡面寫資料庫的連線密碼,不用擔心外洩,因為這些 Code 永遠只會在 Server 的機房裡執行。
在 Vibe Tutor 中,我們的課程閱讀頁面 (src/app/courses/[...slug]/page.tsx) 就是最典型的 Server Component。它直接在伺服器讀取本機的 Markdown 檔案並轉換成 HTML,確保你的萬字長文一秒載入,且被 Google 完美收錄。
2. Client Components (客戶端元件)
如果一個元件需要「互動」,例如:
- 點擊按鈕跳出彈窗 (
onClick) - 使用
useState記住狀態 - 使用
useEffect監聽瀏覽器捲動 - 使用需要依賴瀏覽器 API 的動畫庫 (如 Framer Motion)
那它就必須是 Client Component。你只需要在檔案的「第一行」加上魔法宣告:
"use client";
加上這行後,它就會像傳統的 React 一樣,把 JS 傳到瀏覽器端運作了。
在 Vibe Tutor 中,結帳頁面的定價卡片切換 (src/app/pricing/page.tsx) 或是導覽列的手機版漢堡選單,就是 Client Component 的最佳範例。
💡 架構師心法: 盡可能讓你的網頁保持是 Server Component。只有在樹狀結構的「末端葉子節點」(例如一顆會按下去會跳出的按鈕),才將那個小元件切出去變成 Client Component。這能確保整個頁面的效能最大化。
🗺️ 路由設計 (Routing) 的藝術:資料夾即網址
App Router 徹底改變了網址 (URL) 產生的方式,它採用了極度直覺的「資料夾結構路由 (File-system Based Routing)」。
在我們的 src/app/ 資料夾下,每一個有包含 page.tsx 的資料夾,就會自動變成一個網址節點。
例如:
src/app/page.tsx➡️https://你的網域.com/(首頁)src/app/pricing/page.tsx➡️https://你的網域.com/pricing(定價頁)src/app/dashboard/page.tsx➡️https://你的網域.com/dashboard(會員中心)
動態路由 (Dynamic Routes):自動長出無限頁面
那如果我們有 1,000 堂課程呢?總不能手動建 1,000 個資料夾吧?
我們使用了 Next.js 的動態路由功能,也就是資料夾名稱加上中括號:[...slug]。
來看看 src/app/courses/[...slug]/page.tsx 這個神妙的設計。
這裡的 [...slug] (稱為 Catch-all Segments) 可以接住任何在 /courses/ 後面的網址層級。
- 當使用者連到
/courses/car-camping時,slug參數就是['car-camping']。 - 當連到
/courses/car-camping/01-intro時,slug就是['car-camping', '01-intro']。
我們透過這個 slug 參數,就能在 Server Component 中精準知道使用者現在想看哪一堂課,進而使用 Node.js 的 fs (檔案系統) 去 content/courses/ 底下讀取對應的 Markdown 檔案。
// 擷取自課程頁面原始碼的精華概念
import fs from 'fs';
import path from 'path';
// 這是跑在 Server 端的非同步元件
export default async function CoursePage({ params }: { params: { slug: string[] } }) {
const { slug } = await params;
// 巧妙地利用陣列組合出伺服器內的絕對路徑
const filePath = path.join(process.cwd(), "content", "courses", ...slug) + ".md";
try {
// 瞬間讀取檔案內容
const fileContents = fs.readFileSync(filePath, "utf8");
return <div>{/* 渲染 Markdown 內容 */}</div>;
} catch (error) {
// 找不到檔案就跳去 404 頁面
return <div>找不到這堂課喔!</div>;
}
}
這種設計讓你未來新增任何課程,都完全不需要去動任何一行路由程式碼! 你只要把編輯好的 Markdown 檔案丟進資料夾,網址就自動生成了,這就是一人公司能高效營運的秘密。
📈 效能與分享最佳化:Metadata 與字體
為了讓網站不僅跑得快,還能在社群媒體上引發瘋傳,我們使用了 Next.js 內建的殺手級功能:
-
動態 Metadata API: 在社群行銷中,當你把網址貼到 Line 或 Facebook 時,出現的縮圖、標題、描述,決定了點擊率 (CTR)。 只要在頁面中
export const metadata = { ... },Next.js 就會自動幫你把這些資訊塞進 HTML 的<head>的 OpenGraph 標籤裡。我們甚至能根據讀取的 Markdown 內容,動態生成這堂課專屬的 SEO 標題! -
next/font 閃電字體: 我們在
layout.tsx中使用了next/font/google載入了預設字體。這項技術會在你編譯 (Build) 專案時,將 Google Fonts 直接下載並打包進你的伺服器中。 這完美避免了使用者打開網頁時,還要去 Google 伺服器抓字體所造成的「畫面閃爍與排版偏移 (Cumulative Layout Shift)」。這是提升 Google SEO 核心網頁指標 (Core Web Vitals) 評分的重要小心機。
✅ 本章小結
掌握了 Next.js App Router 的精髓,你的前端架構就已經具備了企業級的穩定度與 SEO 戰鬥力。 有了這副強健的骨架,下一章,我們將來探討如何為它穿上最華麗、最能說服客戶掏錢的外衣:Tailwind CSS 與 Framer Motion 物理微動畫。