【Next.js】路由機制(動態)
在 Next.js 中,**Dynamic Routes(動態路由)**允許你根據 URL 中的參數來動態建立頁面,這對於像是部落格文章、使用者頁面、商品詳細頁等非常有用。
🗂️ 基本概念
在 Next.js 中,每個檔案都對應一個路由。當你在 app/ 或 pages/ 目錄中使用 方括號([param]) 定義檔案名稱時,就代表建立了一個動態路由。
例如:
pages/
└── blog/
└── [slug].tsx
這樣的結構可以對應:
-
/blog/hello-world -
/blog/my-second-post
在 app/ 目錄中則會是:
app/
└── blog/
└── [slug]/
└── page.tsx
💡 Dynamic Routes 實作(pages/)(舊版功能Next13 以前)
1️⃣ 建立檔案:pages/post/[id].tsx
import { useRouter } from 'next/router'
export default function Post() {
const router = useRouter()
const { id } = router.query
return <h1>Post ID: {id}</h1>
}
訪問 /post/123 → 顯示 Post ID: 123
💡 Dynamic Routes 實作(app/)
1️⃣ 建立檔案:app/post/[id]/page.tsx
interface PageProps {
params: { id: string }
}
export default function Post({ params }: PageProps) {
return <h1>Post ID: {params.id}</h1>
}
// { params }: PageProps
// { params } => 解構,取出物件的 params 屬性
// :PageProps typescript宣告型別
// 直接簡化成 { params }: { params: { id: string } }
🔁 多層動態路由
支援巢狀結構,例如:
app/
└── user/
└── [userId]/
└── post/
└── [postId]/
└── page.tsx
訪問路徑 /user/1/post/10 對應的 params 為:
params: {
userId: '1',
postId: '10'
}
✅ Catch-all 路由(捕捉所有)
你可以使用 [...slug] 來捕捉多層級路徑:
-
app/products/[...slug].tsx會匹配/products/a、/products/a/b/c
interface PageProps {
params: {
slug?: string[];
};
}
export default function ProductPage({ params }: PageProps) {
return (
<div>
<h1>Products Page</h1>
<pre>{JSON.stringify(params.slug)}</pre>
</div>
);
}
如果要可選,可用 [[...slug]] 表示非必要。
pages/ vs app/ 差異總覽
| 項目 | pages/ 目錄(Pages Router) |
app/ 目錄(App Router) |
|---|---|---|
| 路由方式 | 檔名對應 URL(傳統) | 檔名+資料夾對應 URL(新式、模組化) |
| 檔案命名 | pages/index.tsx, pages/about.tsx |
app/page.tsx, app/about/page.tsx |
| 動態路由 | [id].tsx |
[id]/page.tsx |
| 資料抓取 (Data Fetching) | getStaticProps, getServerSideProps |
fetch + async component + generateStaticParams |
| 頁面元件 | function component (無 layout 管理) | 支援 layout.tsx, error.tsx, loading.tsx 等 |
| 支援 RSC (React Server Component) | ❌ 僅支援 CSR/SSR/SSG | ✅ 原生支援 Server Components |
| Server Actions | ❌ 不支援 | ✅ 支援(可在伺服器端直接處理表單等邏輯) |
| Incremental Static Regeneration (ISR) | ✅ 支援 | ✅ 支援 |
| 適合對象 | 傳統 SSR/SSG 專案、快速上手 | 複雜應用、大型專案、Server-first 架構 |
📌 小結
| 類型 | 說明 | 範例 |
|---|---|---|
[param] |
基本動態路由 | /post/1 → [id].tsx |
[...param] |
捕捉多層路徑(Catch-all) | /docs/a/b → [...slug].tsx |
[[...param]] |
可選 catch-all(Optional) | /docs or /docs/a |
若你想看實際範例或搭配 getStaticPaths、generateStaticParams 使用,也可以提出,我可以補上。需要嗎?