比較不一樣的作法。
簡述
很多時候我們會碰到動態路由的需求,像是某篇文章的頁面可能是 /posts/id
,還是某樣產品細節頁面是 /products/id
的這種路由,這種時候就需要讓 id
這一段變成是「動態」的。
在 Next 裡面的作法是這樣:
- 把要動態的頁面用
[]
來命名,例如post/[id].js
- 該頁面必須設置
getStaticPaths
來定義所有可能的路由 - 該頁面最後再透過
getStaticProps
並根據路由參數來存取對應的資料
附上官網給的貼切流程:
最後這個頁面的內容會長的像這樣:
1 | import Layout from '../../components/layout' |
附註:關於 getStaticPaths 的回傳格式
上面的範例因為有把 code 拆開來寫所以不是很清楚,getStaticPaths
的回傳值是有遵循某個格式的,不可以亂傳:
1 | const returnValue = { |
為什麼要有 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 頁面存在。也許是因為這樣所以才會這樣命名吧,不過基本上最後的結果會是相同的。