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,
  }))
}

// Несколько версий этой страницы будут статически сгенерированы
// с использованием `params`, возвращенных `generateStaticParams`
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,
  }))
}

// Несколько версий этой страницы будут статически сгенерированы
// с использованием `params`, возвращенных `generateStaticParams`
export default async function Page({ params }) {
  const { slug } = await params
  // ...
}

Полезно знать:

  • Вы можете использовать опцию конфигурации сегмента dynamicParams для управления поведением при посещении динамического сегмента, который не был сгенерирован с помощью generateStaticParams.
  • Для повторной валидации (ISR) путей во время выполнения необходимо либо вернуть пустой массив из generateStaticParams, либо использовать export const dynamic = 'force-static'.
  • В режиме next dev функция generateStaticParams будет вызываться при переходе на маршрут.
  • Во время next build функция generateStaticParams выполняется перед генерацией соответствующих Layouts или Pages.
  • При повторной валидации (ISR) функция generateStaticParams не вызывается снова.
  • generateStaticParams заменяет функцию getStaticPaths в Pages Router.

Параметры

options.params (опционально)

Если несколько динамических сегментов в маршруте используют generateStaticParams, дочерняя функция generateStaticParams выполняется один раз для каждого набора params, сгенерированного родительским компонентом.

Объект params содержит заполненные params из родительской функции generateStaticParams, которые могут быть использованы для генерации 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' }]
}

// Три версии этой страницы будут статически сгенерированы
// с использованием `params`, возвращенных `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 [{ id: '1' }, { id: '2' }, { id: '3' }]
}

// Три версии этой страницы будут статически сгенерированы
// с использованием `params`, возвращенных `generateStaticParams`
// - /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' },
  ]
}

// Три версии этой страницы будут статически сгенерированы
// с использованием `params`, возвращенных `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 [
    { category: 'a', product: '1' },
    { category: 'b', product: '2' },
    { category: 'c', product: '3' },
  ]
}

// Три версии этой страницы будут статически сгенерированы
// с использованием `params`, возвращенных `generateStaticParams`
// - /products/a/1
// - /products/b/2
// - /products/c/3
export default async function Page({ params }) {
  const { category, product } = await params
  // ...
}

Catch-all динамический сегмент

export function generateStaticParams() {
  return [{ slug: ['a', '1'] }, { slug: ['b', '2'] }, { slug: ['c', '3'] }]
}

// Три версии этой страницы будут статически сгенерированы
// с использованием `params`, возвращенных `generateStaticParams`
// - /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'] }]
}

// Три версии этой страницы будут статически сгенерированы
// с использованием `params`, возвращенных `generateStaticParams`
// - /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':

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 или соответствовать (в случае catch-all маршрутов).

Несколько динамических сегментов в маршруте

Вы можете генерировать параметры для динамических сегментов выше текущего layout или страницы, но не ниже. Например, для маршрута app/products/[category]/[product]:

  • app/products/[category]/[product]/page.js может генерировать параметры для обоих [category] и [product].
  • app/products/[category]/layout.js может генерировать параметры только для [category].

Существует два подхода к генерации параметров для маршрута с несколькими динамическими сегментами:

Генерация параметров снизу вверх

Генерация нескольких динамических сегментов из дочернего сегмента маршрута.

// Генерация сегментов для обоих [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 }) {
  // ...
}

Генерация параметров сверху вниз

Сначала генерируйте родительские сегменты и используйте результат для генерации дочерних сегментов.

// Генерация сегментов для [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 может использовать параметры params, возвращенные из родительской функции generateStaticParams, для динамической генерации своих собственных сегментов.

// Генерация сегментов для [product] с использованием `params`, переданных из
// родительской функции `generateStaticParams`
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 }>
}) {
  // ...
}
// Генерация сегментов для [product] с использованием `params`, переданных из
// родительской функции `generateStaticParams`
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 }) {
  // ...
}

Полезно знать: Запросы fetch автоматически мемоизируются для одних и тех же данных во всех функциях с префиксом generate, Layouts, Pages и Server Components. React cache может быть использован, если fetch недоступен.

История версий

ВерсияИзменения
v13.0.0Добавлена функция generateStaticParams.