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
// ...
}
知っておくと良いこと:
dynamicParams
セグメント設定オプションを使用して、generateStaticParams
で生成されなかった動的セグメントにアクセスした場合の動作を制御できます。generateStaticParams
から空の配列を返すか、export const dynamic = 'force-static'
を使用して、実行時のパスを再検証 (ISR) する必要があります。- `next dev` 中は、ルートに移動したときに `generateStaticParams` が呼び出されます。
- `next build` 中は、対応するLayoutsまたはPagesが生成される前に `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' }]
}
// 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 []
}
知っておくと良いこと: `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]` のパラメータ**のみ**を生成できます。
複数の動的セグメントを持つルートのパラメータを生成するには、2つのアプローチがあります。
ボトムアップでパラメータを生成する
子ルーティングセグメントから複数の動的セグメントを生成します。
// 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` が生成する各セグメントに対して1回実行されます。
子 `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 }>
}) {
// ...
}
知っておくと良いこと: `fetch` リクエストは、`generate`-プレフィックス関数、Layouts、Pages、およびServer Components全体で同じデータに対して自動的にメモ化されます。`fetch` が利用できない場合は、Reactの`cache` を使用できます。
バージョン履歴
バージョン | 変更点 |
---|---|
v13.0.0 | `generateStaticParams` が導入されました。 |
この情報はお役に立ちましたか?