generateStaticParams

generateStaticParams 関数は、動的ルートセグメント と組み合わせて使用することで、リクエスト時にオンデマンドで生成する代わりに、ビルド時にルートを静的生成できます。

// [slug] 動的セグメントを埋めるための `params` リストを返す
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
  // ...
}

知っておくと良いこと:

  • dynamicParams セグメント設定オプションを使って、generateStaticParams で生成されなかった動的セグメントにアクセスした時の挙動を制御できます。
  • ランタイムでパスを再検証 (ISR) するには、generateStaticParams から空の配列を返すか、export const dynamic = 'force-static' を使用する必要があります。
  • next dev 中は、ルートにアクセスした時に generateStaticParams が呼び出されます。
  • next build 中は、generateStaticParams は対応するレイアウトやページが生成される前に実行されます。
  • 再検証 (ISR) 中は、generateStaticParams は再度呼び出されません。
  • generateStaticParams は Pages Router の getStaticPaths 関数を置き換えます。

パラメータ

options.params (オプション)

ルート内の複数の動的セグメントで generateStaticParams を使用する場合、親が生成する各 params セットに対して子の generateStaticParams 関数が1回ずつ実行されます。

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` を使って
// このページの3つのバージョンが静的に生成されます
// - /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' },
  ]
}

// `generateStaticParams` が返した `params` を使って
// このページの3つのバージョンが静的に生成されます
// - /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'] }]
}

// `generateStaticParams` が返した `params` を使って
// このページの3つのバージョンが静的に生成されます
// - /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())

  // ビルド時に最初の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,
  }))
}

ランタイムですべてのパスを生成

すべてのパスを初回アクセス時に静的にレンダリングするには、空の配列を返す(ビルド時には何もレンダリングされない)か、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] のみのパラメータを生成できます。

複数の動的セグメントを持つルートのパラメータを生成するには2つの方法があります:

下から上に向けてパラメータを生成

子ルートセグメントから複数の動的セグメントを生成します。

// [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] セグメントを生成
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 が生成する各セグメントに対して1回ずつ実行されます。

子の 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 }>
}) {
  // ...
}

知っておくと良いこと: fetch リクエストは、すべての generate プレフィックス付き関数、レイアウト、ページ、サーバーコンポーネント間で同じデータに対して自動的にメモ化されます。fetch が利用できない場合は、React の cache を使用できます

バージョン履歴

バージョン変更内容
v13.0.0generateStaticParams が導入されました。