generateStaticParams
generateStaticParams
函數可與動態路由區段結合使用,用於在建置時靜態生成路由,而非在請求時按需生成。
// 返回一個 `params` 列表來填充 [slug] 動態區段
export async function generateStaticParams() {
const posts = await fetch('https://.../posts').then((res) => res.json())
return posts.map((post) => ({
slug: post.slug,
}))
}
// 將會使用 `generateStaticParams` 返回的 `params` 靜態生成此頁面的多個版本
export default async function Page({
params,
}: {
params: Promise<{ slug: string }>
}) {
const { slug } = await params
// ...
}
// 返回一個 `params` 列表來填充 [slug] 動態區段
export async function generateStaticParams() {
const posts = await fetch('https://.../posts').then((res) => res.json())
return posts.map((post) => ({
slug: post.slug,
}))
}
// 將會使用 `generateStaticParams` 返回的 `params` 靜態生成此頁面的多個版本
export default async function Page({ params }) {
const { slug } = await params
// ...
}
須知事項:
- 您可以使用
dynamicParams
區段配置選項來控制當訪問未由generateStaticParams
生成的動態區段時會發生什麼。- 您必須從
generateStaticParams
返回一個空陣列或使用export const dynamic = 'force-static'
才能在執行時重新驗證 (ISR) 路徑。- 在
next dev
期間,當您導航到路由時會呼叫generateStaticParams
。- 在
next build
期間,generateStaticParams
會在生成相應的 Layouts 或 Pages 之前執行。- 在重新驗證 (ISR) 期間,不會再次呼叫
generateStaticParams
。generateStaticParams
取代了 Pages Router 中的getStaticPaths
函數。
參數
options.params
(選填)
如果路由中的多個動態區段使用 generateStaticParams
,則會針對父級生成的每組 params
執行一次子級 generateStaticParams
函數。
params
物件包含來自父級 generateStaticParams
的已填充 params
,可用於在子區段中生成 params
。
返回值
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' }]
}
// 將會使用 `generateStaticParams` 返回的 `params` 靜態生成此頁面的三個版本
// - /product/1
// - /product/2
// - /product/3
export default async function Page({
params,
}: {
params: Promise<{ id: string }>
}) {
const { id } = await params
// ...
}
export function generateStaticParams() {
return [{ id: '1' }, { id: '2' }, { id: '3' }]
}
// 將會使用 `generateStaticParams` 返回的 `params` 靜態生成此頁面的三個版本
// - /product/1
// - /product/2
// - /product/3
export default async function Page({ params }) {
const { id } = await params
// ...
}
多個動態區段
export function generateStaticParams() {
return [
{ category: 'a', product: '1' },
{ category: 'b', product: '2' },
{ category: 'c', product: '3' },
]
}
// 將會使用 `generateStaticParams` 返回的 `params` 靜態生成此頁面的三個版本
// - /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 [
{ category: 'a', product: '1' },
{ category: 'b', product: '2' },
{ category: 'c', product: '3' },
]
}
// 將會使用 `generateStaticParams` 返回的 `params` 靜態生成此頁面的三個版本
// - /products/a/1
// - /products/b/2
// - /products/c/3
export default async function Page({ params }) {
const { category, product } = await params
// ...
}
萬用動態區段
export function generateStaticParams() {
return [{ slug: ['a', '1'] }, { slug: ['b', '2'] }, { slug: ['c', '3'] }]
}
// 將會使用 `generateStaticParams` 返回的 `params` 靜態生成此頁面的三個版本
// - /product/a/1
// - /product/b/2
// - /product/c/3
export default async function Page({
params,
}: {
params: Promise<{ slug: string[] }>
}) {
const { slug } = await params
// ...
}
export function generateStaticParams() {
return [{ slug: ['a', '1'] }, { slug: ['b', '2'] }, { slug: ['c', '3'] }]
}
// 將會使用 `generateStaticParams` 返回的 `params` 靜態生成此頁面的三個版本
// - /product/a/1
// - /product/b/2
// - /product/c/3
export default async function Page({ params }) {
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())
return posts.map((post) => ({
slug: post.slug,
}))
}
在建置時生成部分路徑
要在建置時靜態渲染部分路徑,並在首次訪問時於執行時渲染其餘路徑,請返回部分路徑列表:
export async function generateStaticParams() {
const posts = await fetch('https://.../posts').then((res) => res.json())
// 在建置時渲染前 10 篇文章
return posts.slice(0, 10).map((post) => ({
slug: post.slug,
}))
}
export async function generateStaticParams() {
const posts = await fetch('https://.../posts').then((res) => res.json())
// 在建置時渲染前 10 篇文章
return posts.slice(0, 10).map((post) => ({
slug: post.slug,
}))
}
然後,通過使用 dynamicParams
區段配置選項,您可以控制當訪問未由 generateStaticParams
生成的動態區段時會發生什麼。
// 除了前 10 篇之外的所有文章將返回 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,
}))
}
// 除了前 10 篇之外的所有文章將返回 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 []
}
須知事項: 您必須始終從
generateStaticParams
返回一個陣列,即使它是空的。否則,路由將被動態渲染。
export const dynamic = 'force-static'
禁用未指定路徑的渲染
要防止在執行時靜態渲染未指定的路徑,請在路由區段中添加 export const dynamicParams = false
選項。使用此配置選項時,僅會提供由 generateStaticParams
生成的路徑,未指定的路由將返回 404 或匹配(對於萬用路由)。
路由中的多個動態區段
您可以為當前 Layout 或 Page 上方的動態區段生成 params,但不能為下方的區段生成。例如,對於 app/products/[category]/[product]
路由:
app/products/[category]/[product]/page.js
可以為[category]
和[product]
兩者生成 params。app/products/[category]/layout.js
只能為[category]
生成 params。
有兩種方法可以為具有多個動態區段的路由生成 params:
從下往上生成 params
從子路由區段生成多個動態區段。
// 為 [category] 和 [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 }>
}) {
// ...
}
// 為 [category] 和 [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
先生成父級區段,然後使用結果生成子級區段。
// 為 [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 }>
}) {
// ...
}
// 為 [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 }) {
// ...
}
子路由區段的 generateStaticParams
函數會針對父級 generateStaticParams
生成的每個區段執行一次。
子級 generateStaticParams
函數可以使用從父級 generateStaticParams
函數返回的 params
來動態生成自己的區段。
// 使用從父級區段的 `generateStaticParams` 函數傳遞的 `params` 為 [product] 生成區段
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 }>
}) {
// ...
}
// 使用從父級區段的 `generateStaticParams` 函數傳遞的 `params` 為 [product] 生成區段
export async function generateStaticParams({ params: { category } }) {
const products = await fetch(
`https://.../products?category=${category}`
).then((res) => res.json())
return products.map((product) => ({
product: product.id,
}))
}
export default function Page({ params }) {
// ...
}
須知事項: 對於所有以
generate
為前綴的函數、Layouts、Pages 和 Server Components,fetch
請求會自動記憶化。如果無法使用fetch
,可以使用 React 的cache
函數。
版本歷史
版本 | 變更內容 |
---|---|
v13.0.0 | 引入 generateStaticParams 。 |