跳至内容
API 参考函数generateStaticParams

generateStaticParams

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

app/blog/[slug]/page.js
// 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 }) {
  const { slug } = await params
  // ...
}

需要了解:

  • 您可以使用dynamicParams 段配置选项来控制当访问使用 generateStaticParams 未生成的动态段时会发生什么。
  • 您必须从 generateStaticParams返回一个空数组或在export const dynamic = 'force-static'中使用,以便在运行时重新验证 (ISR) 路径
  • next dev 期间,当您导航到路由时,将调用 generateStaticParams
  • next build 期间,generateStaticParams 在生成相应的布局或页面之前运行。
  • 在重新验证 (ISR) 期间,不会再次调用 generateStaticParams
  • generateStaticParams 替换了页面路由器中的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[] }[]

单个动态段

app/product/[id]/page.tsx
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: { id: string } }) {
  const { id } = await params
  // ...
}

多个动态段

app/products/[category]/[product]/page.tsx
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: { category: string; product: string }
}) {
  const { category, product } = await params
  // ...
}

通配符动态段

app/product/[...slug]/page.tsx
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: { slug: string[] } }) {
  const { slug } = await params
  // ...
}

示例

静态渲染

构建时渲染所有路径

要静态渲染构建时所有路径,请将完整路径列表提供给generateStaticParams

app/blog/[slug]/page.tsx
export async function generateStaticParams() {
  const posts = await fetch('https://.../posts').then((res) => res.json())
 
  return posts.map((post) => ({
    slug: post.slug,
  }))
}

构建时渲染部分路径

要静态渲染构建时部分路径,并在运行时首次访问剩余路径时渲染,请返回部分路径列表

app/blog/[slug]/page.tsx
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生成的动态段时发生的情况。

app/blog/[slug]/page.js
// 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'

app/blog/[slug]/page.js
export async function generateStaticParams() {
  return []
}

注意:即使是空数组,也必须始终从generateStaticParams返回数组。否则,路由将被动态渲染。

app/changelog/[slug]/page.js
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]生成参数。

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

自下而上生成参数

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

app/products/[category]/[product]/page.tsx
// 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 }
}) {
  // ...
}

自上而下生成参数

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

app/products/[category]/layout.tsx
// 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 } }) {
  // ...
}

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

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

app/products/[category]/[product]/page.tsx
// 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为前缀的函数、布局、页面和服务器组件,fetch请求都会自动进行记忆化。如果fetch不可用,可以使用Reactcache

版本历史

版本更改
v13.0.0引入generateStaticParams