Blog

Next.js APP Router

Next.js 在約 2022 年年底發布了 App Router,剛推出時其實爭議不小,當時 Bug 較多且 Performance 問題也時有所聞。當然,Vercel 團隊這兩年來也不斷努力,將 App Router 的功能修補得更完善、更穩定。

經過兩年的觀察與評估,我們認為 App Router 的生態系已經相當成熟。因此,因創科技在今年年初開始正式導入,目前新的專案也全面採用 App Router 進行開發。

這篇文章將介紹 App Router 的關鍵新功能與架構改變,並分享一些我們在實際開發中的經驗供大家參考。

1. 檔案架構改變

App Router 改變最大的莫過於檔案架構與路由邏輯:

  • /pages to /app 原本 Pages Router 的頁面檔案都放在 /pages 目錄下,而 App Router 則統一移至 /app 目錄下。這不僅是路徑的改變,更代表了底層渲染邏輯的區隔。
  • 動態路由 (Dynamic Routes) 在 Pages Router 中,動態路由直接寫在檔案名稱上,例如 [slugs].tsx (或是 [...slugs].tsx)。但在 App Router 中,路由必須由資料夾 (Folder) 來定義,實際的頁面內容則統一命名為 page.tsx

    範例: /app/blog/[slug]/page.tsx

  • 特殊檔案約定 (Special Files) App Router 除了 page.tsx 之外,還加上了許多功能性的特殊檔案名稱,例如 loading.tsx (處理載入狀態)、error.tsx (處理錯誤) 以及 not-found.tsx,讓開發者能更直觀地處理各種 UI 狀態。
  • _app.tsx to layout.tsx 原本的全域入口 _app.tsxlayout.tsx 取代。App Router 也支援 Nested Layouts每個資料夾層級都可以有自己的 layout.tsx,子目錄會自動繼承父層的 Layout,大幅減少了重複程式碼的撰寫,也解決了過去在換頁時 Layout 狀態難以保留的問題。

2. 快取與資料獲取機制 (Caching & Data Fetching)

App Router 的快取機制與過去截然不同,提供了更細更其強大的控制:

在舊版 Pages Router,我們只能在頁面層級設定 revalidate 參數(ISR),或是透過 API 手動清除快取。

新版 App Router 則是基於 Web Standard 的 fetch API 進行擴充。除了原本的 revalidate 時間設定外,我們現在可以針對每一個 API 請求設定快取標籤 (Tags)。這讓我們能透過 revalidateTag 精準地清除特定資料的快取,而不需要重建整個頁面,大幅提升了資料更新的效率與彈性。

// 快取設定範例:每小時(3600 秒清除快取), 加上 posts tag fetch('https://...', { next: { revalidate: 3600, tags: ['posts'] } })
//清除所有有用到 posts tag 的頁面 revalidateTag('posts', "max");

**小心踩雷**

  1. 如果你在頁面有定義 revalidate 參數,而這個頁面又有元件需要使用 fetch 抓資料(架設也有使用 revalidate),那這個頁面的快取會以最小的參數為主。eg. 假設頁面的 revalidate 參數為 3600 * 24 (一天),而 fetch 的 revalidate 為 3600,則這個頁面一樣會每小時重新 render 一次。
  2. 如果頁面使用的 fetch 沒有設定 revalidate 或是 revalidate 設定為 0,那這個頁面會完全不被快取,而是每次都是重新 Dynamic Render。

3. Client & Server Components

這是一個非常重大的觀念轉變。App Router 全面支援 React Server Components (RSC)

簡單來說,在 App Router 中,所有的 Component 預設都是 Server Component,這意味著它們只會在伺服器端執行渲染,不會被打包到前端的 JavaScript Bundle 中。只有當你在檔案頂端加上 "use client" 指令時,該元件才會變成 Client Component(類似過去我們熟悉的 React 元件)。

為什麼要這樣分?主要有三個好處:

  1. 前端 Payload 變小: 因為 Server Component 的邏輯與依賴套件不會被傳送到瀏覽器,使用者的下載量變少,網站載入速度顯著提升。
  2. 更高的安全性: Server Component 可以直接在元件內安全地讀取資料庫或使用 API Key,而不必擔心機密資訊洩漏到前端。
  3. Server Actions: 我們可以直接在 Component 內撰寫 Server Functions 來處理表單送出 (Form Actions) 或資料篩選。這讓我們在很多簡單的場景下,不再需要額外撰寫 API Route (/api/...),簡化了前後端的溝通成本。

結論

新的技術一定會帶來新的學習曲線與改變,相反地,也有可能將大家習慣的一些舊功能移除。對我們來說,App Router 確實讓開發變得更有彈性且功能強大,但也並非沒有痛點(例如:原本支援的 root domain locale 功能被移除,雖然可透過 Middleware 解決,但稍微增加了複雜度)。

總結來說,升級到 App Router 是利大於弊的。

因創科技會持續評估並測試新技術,在確保安全與穩定的前提下,致力於提供客戶不只是最新,更是最「合適」的解決方案。

文章最後更新於 : 2025.11.27