getStaticPaths (取得靜態路徑)
當您從使用動態路由的頁面匯出名為 getStaticPaths
的函式時,Next.js 會靜態預渲染 getStaticPaths
指定的所有路徑。
import type {
InferGetStaticPropsType,
GetStaticProps,
GetStaticPaths,
} from 'next'
type Repo = {
name: string
stargazers_count: number
}
export const getStaticPaths = (async () => {
return {
paths: [
{
params: {
name: 'next.js',
},
}, // See the "paths" section below
],
fallback: true, // false or "blocking"
}
}) satisfies GetStaticPaths
export const getStaticProps = (async (context) => {
const res = await fetch('https://api.github.com/repos/vercel/next.js')
const repo = await res.json()
return { props: { repo } }
}) satisfies GetStaticProps<{
repo: Repo
}>
export default function Page({
repo,
}: InferGetStaticPropsType<typeof getStaticProps>) {
return repo.stargazers_count
}
getStaticPaths 的回傳值
getStaticPaths
函式應該回傳一個物件,其中包含以下**必要**屬性:
paths
的頁面,命名為 pages/posts/[id].js
。如果您從這個頁面匯出 getStaticPaths
並為 paths
回傳以下內容:
return {
paths: [
{ params: { id: '1' }},
{
params: { id: '2' },
// with i18n configured the locale for the path can be returned as well
locale: "en",
},
],
fallback: ...
}
return {
paths: [
{ params: { id: '1' }},
{
params: { id: '2' },
// with i18n configured the locale for the path can be returned as well
locale: "en",
},
],
fallback: ...
}
那麼,Next.js 將在 next build
期間使用 pages/posts/[id].js
中的頁面組件靜態生成 /posts/1
和 /posts/2
。
每個 params
物件的值必須與頁面名稱中使用的參數相符。
- 如果頁面名稱是
pages/posts/[postId]/[commentId]
,那麼params
應該包含postId
和commentId
。 - 如果頁面名稱使用全捕捉路由,例如
pages/[...slug]
,則params
應該包含slug
(它是一個陣列)。如果這個陣列是['hello', 'world']
,那麼 Next.js 將在/hello/world
靜態生成頁面。 - 如果頁面使用可選的全捕捉路由,請使用
null
、[]
、undefined
或false
來渲染最根部的路由。例如,如果您為pages/[[...slug]]
提供slug: false
,Next.js 將靜態生成頁面/
。
params
字串**區分大小寫**,理想情況下應該標準化以確保路徑正確生成。例如,如果為參數回傳 WoRLD
,則它只會在實際訪問的路徑是 WoRLD
時匹配,而不是 world
或 World
。
除了 params
物件之外,當設定 i18n 時,可以回傳一個 locale
欄位,它會設定正在生成的路径的語系。
fallback: false
如果 fallback
為 false
,則任何未由 getStaticPaths
回傳的路徑都將導致**404 頁面**。
當執行 next build
時,Next.js 會檢查 getStaticPaths
是否返回 fallback: false
,如果是,則**只**會建置 getStaticPaths
返回的路徑。如果您只需建立少量路徑,或者頁面資料不常新增,則此選項很有用。如果您發現需要新增更多路徑,且您設定了 fallback: false
,則需要再次執行 next build
才能產生新的路徑。
以下範例會針對名為 pages/posts/[id].js
的每個頁面預先渲染一篇部落格文章。部落格文章列表將從 CMS 擷取並由 getStaticPaths
返回。然後,針對每個頁面,它會使用 getStaticProps
從 CMS 擷取文章資料。
function Post({ post }) {
// Render post...
}
// This function gets called at build time
export async function getStaticPaths() {
// Call an external API endpoint to get posts
const res = await fetch('https://.../posts')
const posts = await res.json()
// Get the paths we want to pre-render based on posts
const paths = posts.map((post) => ({
params: { id: post.id },
}))
// We'll pre-render only these paths at build time.
// { fallback: false } means other routes should 404.
return { paths, fallback: false }
}
// This also gets called at build time
export async function getStaticProps({ params }) {
// params contains the post `id`.
// If the route is like /posts/1, then params.id is 1
const res = await fetch(`https://.../posts/${params.id}`)
const post = await res.json()
// Pass post data to the page via props
return { props: { post } }
}
export default Post
fallback: true
範例
如果 fallback
設定為 true
,則 getStaticProps
的行為將會以下列方式改變:
- 建置時,
getStaticPaths
返回的路徑將會由getStaticProps
渲染成HTML
。 - 建置時未產生的路徑**不會**導致 404 頁面。相反地,Next.js 會在第一次請求此類路徑時提供頁面的「fallback」版本。網路爬蟲(例如 Google)不會收到 fallback 版本,而是如同
fallback: 'blocking'
的行為。 - 當透過
next/link
或next/router
(客戶端)瀏覽到fallback: true
的頁面時,Next.js **不會**提供 fallback 版本,而是如同fallback: 'blocking'
的行為。 - 在背景中,Next.js 會靜態產生所請求路徑的
HTML
和JSON
。這包括執行getStaticProps
。 - 完成後,瀏覽器會收到已產生路徑的
JSON
。這將用於使用所需的 props 自動渲染頁面。從使用者的角度來看,頁面將會從 fallback 頁面切換到完整頁面。 - 同時,Next.js 會將此路徑新增到預先渲染的頁面列表中。後續對相同路徑的請求將會提供已產生的頁面,就像其他在建置時預先渲染的頁面一樣。
注意事項:使用
output: 'export'
時,不支援fallback: true
。
什麼時候fallback: true
很有用?
當您的應用程式有大量依賴數據的靜態頁面時(例如大型電商網站),fallback: true
就很有用。如果您想要預先渲染所有產品頁面,建置過程將會耗費很長時間。
此時,您可以改為靜態生成一小部分頁面,並將其餘頁面設定為 fallback: true
。當有人請求尚未生成的頁面時,使用者會看到顯示載入指示器或骨架組件的頁面。
不久之後,getStaticProps
完成,頁面將會使用請求的數據進行渲染。從此刻起,所有請求相同頁面的使用者都將獲得靜態預渲染的頁面。
這確保了使用者始終擁有快速體驗,同時保持快速建置和靜態生成的優勢。
fallback: true
不會*更新*已生成的頁面,關於更新頁面,請參考 增量靜態再生。
fallback: 'blocking'
如果 fallback
設定為 'blocking'
,getStaticPaths
未返回的新路徑將會等待 HTML
生成,與 SSR 相同(因此稱為*阻塞*),然後會快取以供將來的請求使用,因此每個路徑只會發生一次。
getStaticProps
的行為如下:
- 建置時,
getStaticPaths
返回的路徑將會由getStaticProps
渲染成HTML
。 - 建置時未生成的 pathways 將不會導致 404 頁面。相反地,Next.js 將在第一次請求時進行 SSR 並返回生成的
HTML
。 - 完成後,瀏覽器會收到已生成路徑的
HTML
。從使用者的角度來看,它將從「瀏覽器正在請求頁面」轉變為「完整頁面已載入」。不會閃爍載入/後備狀態。 - 同時,Next.js 會將此路徑新增到預先渲染的頁面列表中。後續對相同路徑的請求將會提供已產生的頁面,就像其他在建置時預先渲染的頁面一樣。
預設情況下,fallback: 'blocking'
不會*更新*已生成的頁面。要更新已生成的頁面,請將 增量靜態再生 與 fallback: 'blocking'
搭配使用。
注意事項:使用
output: 'export'
時,不支援fallback: 'blocking'
。
後備頁面
在頁面的「後備」版本中
- 頁面的 props 將會是空的。
- 使用 路由器,您可以偵測後備是否正在渲染,
router.isFallback
將會是true
。
以下範例展示如何使用 isFallback
import { useRouter } from 'next/router'
function Post({ post }) {
const router = useRouter()
// If the page is not yet generated, this will be displayed
// initially until getStaticProps() finishes running
if (router.isFallback) {
return <div>Loading...</div>
}
// Render post...
}
// This function gets called at build time
export async function getStaticPaths() {
return {
// Only `/posts/1` and `/posts/2` are generated at build time
paths: [{ params: { id: '1' } }, { params: { id: '2' } }],
// Enable statically generating additional pages
// For example: `/posts/3`
fallback: true,
}
}
// This also gets called at build time
export async function getStaticProps({ params }) {
// params contains the post `id`.
// If the route is like /posts/1, then params.id is 1
const res = await fetch(`https://.../posts/${params.id}`)
const post = await res.json()
// Pass post data to the page via props
return {
props: { post },
// Re-generate the post at most once per second
// if a request comes in
revalidate: 1,
}
}
export default Post
版本歷史記錄
版本 | 變更 |
---|---|
v13.4.0 | 應用程式路由器 (App Router) 現已穩定,並簡化了資料擷取,包含 generateStaticParams() |
v12.2.0 | 隨需增量靜態再生 (On-Demand Incremental Static Regeneration) 現已穩定。 |
v12.1.0 | 新增 隨需增量靜態再生 (On-Demand Incremental Static Regeneration)(測試版)。 |
v9.5.0 | 穩定的 增量靜態再生 (Incremental Static Regeneration) |
v9.3.0 | 引入 getStaticPaths 。 |
這有幫助嗎?