Skip to main content

generateStaticParams

generateStaticParams 功能可以在构建时与 动态路由段静态生成 路由结合使用,而不是在请求时按需使用。

¥The generateStaticParams function can be used in combination with dynamic route segments to statically generate routes at build time instead of on-demand at request time.

// 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 function Page({ params }) {
const { slug } = params
// ...
}

很高兴知道

¥Good to know

  • 你可以使用 dynamicParams 段配置选项来控制当访问不是由 generateStaticParams 生成的动态段时会发生什么情况。

    ¥You can use the dynamicParams segment config option to control what happens when a dynamic segment is visited that was not generated with generateStaticParams.

  • next dev 期间,当你导航到某个路由时,将会调用 generateStaticParams

    ¥During next dev, generateStaticParams will be called when you navigate to a route.

  • next build 期间,generateStaticParams 在生成相应的布局或页面之前运行。

    ¥During next build, generateStaticParams runs before the corresponding Layouts or Pages are generated.

  • 在重新验证 (ISR) 期间,不会再次调用 generateStaticParams

    ¥During revalidation (ISR), generateStaticParams will not be called again.

  • generateStaticParams 取代了页面路由中的 getStaticPaths 功能。

    ¥generateStaticParams replaces the getStaticPaths function in the Pages Router.

参数

¥Parameters

options.params(可选)

¥options.params (optional)

如果路由中的多个动态段使用 generateStaticParams,则对于父级生成的每组 params,子级 generateStaticParams 函数都会执行一次。

¥If multiple dynamic segments in a route use generateStaticParams, the child generateStaticParams function is executed once for each set of params the parent generates.

params 对象包含从父级 generateStaticParams 填充的 params,可用于 在子段中生成 params

¥The params object contains the populated params from the parent generateStaticParams, which can be used to generate the params in a child segment.

返回

¥Returns

generateStaticParams 应返回一个对象数组,其中每个对象代表单个路由的填充动态段。

¥generateStaticParams should return an array of objects where each object represents the populated dynamic segments of a single route.

  • 对象中的每个属性都是要为路由填充的动态段。

    ¥Each property in the object is a dynamic segment to be filled in for the route.

  • 属性名称是段的名称,属性值是该段应填写的内容。

    ¥The properties name is the segment's name, and the properties value is what that segment should be filled in with.

示例路由generateStaticParams 返回类型
/product/[id]{ id: string }[]
/products/[category]/[product]{ category: string, product: string }[]
/products/[...slug]{ slug: string[] }[]

单一动态段

¥Single Dynamic Segment

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 function Page({ params }: { params: { id: string } }) {
const { id } = params
// ...
}
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 function Page({ params }) {
const { id } = params
// ...
}

多个动态片段

¥Multiple Dynamic Segments

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 function Page({
params,
}: {
params: { category: string; product: string }
}) {
const { category, product } = 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 function Page({ params }) {
const { category, product } = params
// ...
}

捕获所有动态片段

¥Catch-all Dynamic Segment

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 function Page({ params }: { params: { slug: string[] } }) {
const { slug } = 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 function Page({ params }) {
const { slug } = params
// ...
}

示例

¥Examples

路由中的多个动态路段

¥Multiple Dynamic Segments in a Route

你可以为当前布局或页面上方的动态段生成参数,但不能在下方生成参数。例如,给定 app/products/[category]/[product] 路由:

¥You can generate params for dynamic segments above the current layout or page, but not below. For example, given the app/products/[category]/[product] route:

  • app/products/[category]/[product]/page.js 可以为 [category][product] 生成参数。

    ¥app/products/[category]/[product]/page.js can generate params for both [category] and [product].

  • app/products/[category]/layout.js 只能为 [category] 生成参数。

    ¥app/products/[category]/layout.js can only generate params for [category].

有两种方法可以为具有多个动态段的路由生成参数:

¥There are two approaches to generating params for a route with multiple dynamic segments:

自下而上生成 params

¥Generate params from the bottom up

从子路由段生成多个动态段。

¥Generate multiple dynamic segments from the child route segment.

// 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: { category: string; product: string }
}) {
// ...
}
// 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 }) {
// ...
}

从上到下生成参数

¥Generate params from the top down

首先生成父段,然后使用结果生成子段。

¥Generate the parent segments first and use the result to generate the child segments.

// 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: { category: 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 }) {
// ...
}

子路由段的 generateStaticParams 函数针对父路由 generateStaticParams 生成的每个段执行一次。

¥A child route segment's generateStaticParams function is executed once for each segment a parent generateStaticParams generates.

generateStaticParams 函数可以使用从父 generateStaticParams 函数返回的 params 来动态生成自己的段。

¥The child generateStaticParams function can use the params returned from the parent generateStaticParams function to dynamically generate its own segments.

// 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: { category: string; product: string }
}) {
// ...
}
// Generate segments for [product] using the `params` passed from
// the parent segment's `generateStaticParams` function
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 前缀的函数、布局、页面和服务器组件中的相同数据,fetch 请求自动为 memoized。如果 fetch 不可用,则响应 可以使用 cache

¥Good to know: fetch requests are automatically memoized for the same data across all generate-prefixed functions, Layouts, Pages, and Server Components. React cache can be used if fetch is unavailable.

仅生成参数的子集

¥Generate only a subset of params

你可以通过返回仅包含要生成的动态段的对象数组来生成路由的参数子集。然后,通过使用 dynamicParams 段配置选项,你可以控制当访问不是使用 generateStaticParams 生成的动态段时会发生什么情况。

¥You can generate a subset of params for a route by returning an array of objects with only the dynamic segments you want to generate. Then, by using the dynamicParams segment config option, you can control what happens when a dynamic segment is visited that was not generated with 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,
}))
}

版本历史

¥Version History

版本变化
v13.0.0generateStaticParams 推出。