Next.js-動態路由

比較不一樣的作法。

簡述

很多時候我們會碰到動態路由的需求,像是某篇文章的頁面可能是 /posts/id,還是某樣產品細節頁面是 /products/id 的這種路由,這種時候就需要讓 id 這一段變成是「動態」的。

在 Next 裡面的作法是這樣:

  1. 把要動態的頁面用 [] 來命名,例如 post/[id].js
  2. 該頁面必須設置 getStaticPaths 來定義所有可能的路由
  3. 該頁面最後再透過 getStaticProps 並根據路由參數來存取對應的資料

附上官網給的貼切流程:

dynamic-routes

最後這個頁面的內容會長的像這樣:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import Layout from '../../components/layout'
import { getAllPostIds, getPostData } from '../../lib/post'

// 1. 取得所有的 [id] 路徑
export async function getStaticPaths() {
const paths = getAllPostIds()
return {
paths,
fallback: false
}
}

// 2. 這邊就可以存取到 [id],並去打對應的 API 拿資料
export async function getStaticProps({ params }) {
const postData = getPostData(params.id)
return {
props: {
postData
}
}
}

// 3. 最後渲染出畫面(pre-rendering)
export default function Post({ postData }) {
return (
<Layout>
{postData.title}
<br />
{postData.id}
<br />
{postData.date}
</Layout>
)
}

附註:關於 getStaticPaths 的回傳格式

上面的範例因為有把 code 拆開來寫所以不是很清楚,getStaticPaths 的回傳值是有遵循某個格式的,不可以亂傳:

1
2
3
4
5
6
7
8
const returnValue = {
paths: {
params: {
id: data.id.toString()
}
},
fallback: false
}

為什麼要有 getStaticPaths?

這邊想做個補充,因為如果你跟我一樣原本是寫 SPA 的話可能會有點疑惑,「為什麼需要先產生 path 才行?」

首先要在強調一次:Next 是通常是基於 SSR/SSG 來產生網頁內容,所以這代表我們在 build 的時候就必須知道「有多少個頁面要產生?」

假設我們的 /post/[id] 有 10 篇文章,那 Next 就應該要在 Server 產生出 10 個 HTML:

  • /post/1
  • /post/2
  • /post/3
  • ...

所以我們一定要透過某種方式來告訴 Next 這件事情,這個就是 getStaticPaths 背後的含義。

關於 fallback

關於這部分可能有點小複雜,如果想知道更詳細的內容我推薦看 這篇文章,講的還蠻清楚的。這邊我只會大概說一下每種 option 的用途。

fallback: false

這個就是假設 user 到了沒有產生的頁面時,Next 會自動跳轉到 404 頁面。

fallback: true

當 user 到了沒有產生的頁面時,Next 會走這樣的流程:

  • 開始動態產生新的內容(getStaticProps),並進入 fallback loading 的狀態(或稱為 fallback 頁面),這個狀態可以透過 router.isFallback 來取得。
  • HTML 生成完以後把結果秀出來
  • 下次造訪相同頁面時,不需要再重新產生一次

fallback: block

這個就跟 true 流程差不多,唯一的差別是沒有 router.isFallback 可以存取,等於說在動態產生的這段期間是「卡住(blocking)」的,不會有 fallback 頁面存在。也許是因為這樣所以才會這樣命名吧,不過基本上最後的結果會是相同的。

Next.js-Incremental Static Regeneration Next.js-獲取資料(getStaticProps)
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×