Next.js Pages Router (遺留系統與遷移指南)

在 Next.js 13 推出 App Router 之前,Pages Router 是 Next.js 的黃金標準。雖然新專案應優先使用 App Router,但在許多企業級專案中,Pages Router 依然佔有一席之地。

本篇旨在幫助你維護舊專案,並提供一條清晰的遷移路徑。

核心架構差異

特性Pages Router (pages/)App Router (app/)
路由定義檔案系統即路由 (index.tsx)資料夾即路由 (page.tsx)
渲染預設Client Side ( hydration )Server Components (預設)
資料擷取getStaticProps / getServerSidePropsasync/await 直接在組件內
佈局 (Layout)_app.tsx (全域單一)巢狀 Layouts (layout.tsx)

資料擷取函式 (Data Fetching Methods)

Pages Router 不支援在組件內直接 async/await,必須透過特定的 export function。

getStaticProps (SSG)

在 Build Time 執行,將 props 傳入頁面組件。

// pages/blog/[slug].tsx
export async function getStaticProps(context) {
  const post = await db.post.findUnique({ where: { slug: context.params.slug } });
  return {
    props: { post },
    revalidate: 60, // ISR: 每 60 秒重新生成
  };
}

export async function getStaticPaths() {
  // 定義哪些路徑要預先生成
  return {
    paths: [{ params: { slug: 'hello-world' } }],
    fallback: 'blocking',
  };
}

getServerSideProps (SSR)

在這個函式內的程式碼,每次請求都會執行

// pages/profile.tsx
export async function getServerSideProps(context) {
  const session = await getSession(context.req);
  if (!session) {
    return {
      redirect: { destination: '/login', permanent: false },
    };
  }
  return { props: { user: session.user } };
}

遷移對照表 (Migration Cheat Sheet)

如果你正在將專案從 Pages 遷移到 App Router,請參考以下對照:

A. 資料擷取 (Data Fetching)

舊 (Pages):

export async function getStaticProps() {
  const data = await getData();
  return { props: { data } };
}
export default function Page({ data }) { ... }

新 (App):

async function getData() { ... }

export default async function Page() {
  const data = await getData();
  return <div>...</div>;
}

B. 動態路徑 (Dynamic Paths)

  • : getStaticPaths
  • : generateStaticParams (注意:語法和回傳格式略有不同,只需回傳 params 陣列,不需包在 paths 物件裡)。

C. 路由 Hook (Router Hooks)

  • : import { useRouter } from 'next/router'
  • :
    • import { useRouter } from 'next/navigation' (僅限 Client Component,用於導航)
    • import { useSearchParams } from 'next/navigation' (讀取 Query Params)
    • import { usePathname } from 'next/navigation' (讀取路徑)

共存策略 (Incremental Adoption)

Next.js 允許 pages/app/ 目錄同時存在。這意味著你不需要一次重寫整個網站。

  1. 新功能優先使用 App Router:新建立的頁面直接放在 app/ 下。
  2. 逐步搬移:一次挑選一個路由(例如 /about),將其從 pages/about.tsx 移至 app/about/page.tsx
  3. 解決衝突:如果同一個路徑同時存在於兩者,app/ 目錄的優先權較高。

結語

Pages Router 是 Next.js 成功的基石,它的許設計模式(如檔案系統路由)至今仍被沿用。了解它的運作原理,不僅能幫助你維護舊程式碼,更能讓你深刻體會 App Router 架構演進的精妙之處。