generateStaticParams
generateStaticParams
函數可以與動態路由區段結合使用,以便在建置時靜態產生路由,而不是在請求時按需產生。
// Return a list of `params` to populate the [slug] dynamic segment
export async function generateStaticParams() {
const posts = await fetch('https://.../posts').then((res) => res.json())
return posts.map((post) => ({
slug: post.slug,
}))
}
// Multiple versions of this page will be statically generated
// using the `params` returned by `generateStaticParams`
export default async function Page({
params,
}: {
params: Promise<{ slug: string }>
}) {
const { slug } = await params
// ...
}
Good to know:
- 您可以使用
dynamicParams
區段配置選項來控制在存取未使用generateStaticParams
產生的動態區段時會發生什麼情況。- 您必須從
generateStaticParams
傳回空陣列,或使用export const dynamic = 'force-static'
,才能重新驗證 (ISR) 執行階段的路徑。- 在
next dev
期間,當您導覽至路由時,將會呼叫generateStaticParams
。- 在
next build
期間,generateStaticParams
會在產生對應的版面配置或頁面之前執行。- 在重新驗證 (ISR) 期間,不會再次呼叫
generateStaticParams
。generateStaticParams
取代了 Pages Router 中的getStaticPaths
函數。
Parameters
options.params
(選用)
如果路由中的多個動態區段使用 generateStaticParams
,則子 generateStaticParams
函數會針對父函數產生的每個 params
集合執行一次。
params
物件包含從父 generateStaticParams
填入的 params
,可用於在子區段中產生 params
。
Returns
generateStaticParams
應傳回物件陣列,其中每個物件代表單一路由的填入動態區段。
- 物件中的每個屬性都是要為路由填入的動態區段。
- 屬性名稱是區段的名稱,而屬性值應為該區段應填入的內容。
範例路由 | generateStaticParams 傳回類型 |
---|---|
/product/[id] | { id: string }[] |
/products/[category]/[product] | { category: string, product: string }[] |
/products/[...slug] | { slug: string[] }[] |
單一動態區段
export function generateStaticParams() {
return [{ id: '1' }, { id: '2' }, { id: '3' }]
}
// Three versions of this page will be statically generated
// using the `params` returned by `generateStaticParams`
// - /product/1
// - /product/2
// - /product/3
export default async function Page({
params,
}: {
params: Promise<{ id: string }>
}) {
const { id } = await params
// ...
}
多個動態區段
export function generateStaticParams() {
return [
{ category: 'a', product: '1' },
{ category: 'b', product: '2' },
{ category: 'c', product: '3' },
]
}
// Three versions of this page will be statically generated
// using the `params` returned by `generateStaticParams`
// - /products/a/1
// - /products/b/2
// - /products/c/3
export default async function Page({
params,
}: {
params: Promise<{ category: string; product: string }>
}) {
const { category, product } = await params
// ...
}
全部捕捉動態區段
export function generateStaticParams() {
return [{ slug: ['a', '1'] }, { slug: ['b', '2'] }, { slug: ['c', '3'] }]
}
// Three versions of this page will be statically generated
// using the `params` returned by `generateStaticParams`
// - /product/a/1
// - /product/b/2
// - /product/c/3
export default async function Page({
params,
}: {
params: Promise<{ slug: string[] }>
}) {
const { slug } = await params
// ...
}
範例
靜態呈現
建置時的所有路徑
若要在建置時靜態呈現所有路徑,請將完整路徑清單提供給 generateStaticParams
export async function generateStaticParams() {
const posts = await fetch('https://.../posts').then((res) => res.json())
return posts.map((post) => ({
slug: post.slug,
}))
}
建置時的路徑子集
若要在建置時靜態呈現路徑的子集,並在第一次於執行階段存取時呈現其餘路徑,請傳回部分路徑清單
export async function generateStaticParams() {
const posts = await fetch('https://.../posts').then((res) => res.json())
// Render the first 10 posts at build time
return posts.slice(0, 10).map((post) => ({
slug: post.slug,
}))
}
然後,透過使用 dynamicParams
區段配置選項,您可以控制在存取未使用 generateStaticParams
產生的動態區段時會發生什麼情況。
// All posts besides the top 10 will be a 404
export const dynamicParams = false
export async function generateStaticParams() {
const posts = await fetch('https://.../posts').then((res) => res.json())
const topPosts = posts.slice(0, 10)
return topPosts.map((post) => ({
slug: post.slug,
}))
}
執行階段的所有路徑
若要在第一次存取時靜態呈現所有路徑,請傳回空陣列 (在建置時不會呈現任何路徑) 或使用 export const dynamic = 'force-static'
export async function generateStaticParams() {
return []
}
Good to know: 您必須一律從
generateStaticParams
傳回陣列,即使它是空的也一樣。否則,路由將會動態呈現。
export const dynamic = 'force-static'
停用未指定路徑的呈現
若要防止未指定的路徑在執行階段靜態呈現,請在路由區段中新增 export const dynamicParams = false
選項。使用此配置選項時,只會提供 generateStaticParams
提供的路徑,而未指定的路由將會 404 或比對 (在全部捕捉路由的情況下)。
路由中的多個動態區段
您可以為目前版面配置或頁面上方的動態區段產生參數,但不能在下方。例如,假設路由為 app/products/[category]/[product]
app/products/[category]/[product]/page.js
可以為[category]
和[product]
兩者產生參數。app/products/[category]/layout.js
只能為[category]
產生參數。
有兩種方法可以為具有多個動態區段的路由產生參數
由下而上產生參數
從子路由區段產生多個動態區段。
// Generate segments for both [category] and [product]
export async function generateStaticParams() {
const products = await fetch('https://.../products').then((res) => res.json())
return products.map((product) => ({
category: product.category.slug,
product: product.id,
}))
}
export default function Page({
params,
}: {
params: Promise<{ category: string; product: string }>
}) {
// ...
}
由上而下產生參數
先產生父區段,然後使用結果來產生子區段。
// Generate segments for [category]
export async function generateStaticParams() {
const products = await fetch('https://.../products').then((res) => res.json())
return products.map((product) => ({
category: product.category.slug,
}))
}
export default function Layout({
params,
}: {
params: Promise<{ category: string }>
}) {
// ...
}
子路由區段的 generateStaticParams
函數會針對父 generateStaticParams
產生的每個區段執行一次。
子 generateStaticParams
函數可以使用從父 generateStaticParams
函數傳回的 params
,以動態產生自己的區段。
// Generate segments for [product] using the `params` passed from
// the parent segment's `generateStaticParams` function
export async function generateStaticParams({
params: { category },
}: {
params: { category: string }
}) {
const products = await fetch(
`https://.../products?category=${category}`
).then((res) => res.json())
return products.map((product) => ({
product: product.id,
}))
}
export default function Page({
params,
}: {
params: Promise<{ category: string; product: string }>
}) {
// ...
}
Good to know:
fetch
請求會自動針對跨所有generate
首碼函數、版面配置、頁面和伺服器元件的相同資料進行記憶化。如果fetch
無法使用,則可以使用 Reactcache
。
版本歷程記錄
版本 | 變更 |
---|---|
v13.0.0 | 引入 generateStaticParams 。 |
Was this helpful?