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
函数。
参数
options.params
(可选)
如果路由中的多个动态段使用 generateStaticParams
,则子 generateStaticParams
函数将为父级生成的每组 params
执行一次。
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' }]
}
// 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?