getStaticPaths
Dynamic Routesを使用するページからgetStaticPathsという名前の関数をエクスポートすると、Next.jsはgetStaticPathsで指定されたすべてのパスを静的にプリレンダリングします。
import type {
InferGetStaticPropsType,
GetStaticProps,
GetStaticPaths,
} from 'next'
type Repo = {
name: string
stargazers_count: number
}
export const getStaticPaths = (async () => {
return {
paths: [
{
params: {
name: 'next.js',
},
}, // 以下の"paths"セクションを参照
],
fallback: true, // false または "blocking"
}
}) satisfies GetStaticPaths
export const getStaticProps = (async (context) => {
const res = await fetch('https://api.github.com/repos/vercel/next.js')
const repo = await res.json()
return { props: { repo } }
}) satisfies GetStaticProps<{
repo: Repo
}>
export default function Page({
repo,
}: InferGetStaticPropsType<typeof getStaticProps>) {
return repo.stargazers_count
}getStaticPathsの戻り値
getStaticPaths関数は、以下の必須プロパティを持つオブジェクトを返す必要があります。
paths
pathsキーは、プリレンダリングされるパスを決定します。例えば、pages/posts/[id].jsという名前のDynamic Routesを使用するページがあるとします。このページからgetStaticPathsをエクスポートし、pathsに対して以下を返すとします。
return {
paths: [
{ params: { id: '1' }},
{
params: { id: '2' },
// i18nが設定されている場合、パスのロケールも返すことができます
locale: "en",
},
],
fallback: ...
}その場合、Next.jsはnext build中にpages/posts/[id].jsのページコンポーネントを使用して、/posts/1と/posts/2を静的に生成します。
各paramsオブジェクトの値は、ページ名で使用されるパラメータと一致する必要があります。
- ページ名が
pages/posts/[postId]/[commentId]の場合、paramsはpostIdとcommentIdを含む必要があります。 - ページ名が
pages/[...slug]のようなcatch-all routesを使用する場合、paramsはslugを含む必要があります(配列です)。この配列が['hello', 'world']の場合、Next.jsは/hello/worldでページを静的に生成します。 - ページがoptional catch-all routeを使用する場合、
null、[]、undefined、またはfalseを使用してルート最上位のルートをレンダリングします。例えば、pages/[[...slug]]にslug: falseを指定すると、Next.jsは/でページを静的に生成します。
params文字列は大文字と小文字を区別し、パスが正しく生成されるように正規化することが理想的です。例えば、paramsにWoRLDが返される場合、実際に訪問されるパスがWoRLDの場合にのみマッチし、worldやWorldにはマッチしません。
paramsオブジェクトとは別に、i18nが設定されている場合はlocaleフィールドを返すことができます。これにより、生成されるパスのロケールが設定されます。
fallback: false
fallbackがfalseの場合、getStaticPathsで返されないパスは404ページになります。
next buildが実行されると、Next.jsはgetStaticPathsがfallback: falseを返しているかを確認し、getStaticPathsで返されたパスのみをビルドします。このオプションは、作成するパスの数が少ない場合、または新しいページデータが頻繁に追加されない場合に便利です。より多くのパスを追加する必要があり、fallback: falseを設定している場合は、新しいパスが生成されるようにnext buildを再度実行する必要があります。
以下の例は、pages/posts/[id].jsという名前のページごとに1つのブログ記事をプリレンダリングしています。ブログ記事のリストはCMSから取得され、getStaticPathsで返されます。その後、各ページについて、getStaticPropsを使用してCMSからポストデータを取得します。
function Post({ post }) {
// ポストをレンダリング...
}
// この関数はビルド時に呼び出されます
export async function getStaticPaths() {
// 外部APIエンドポイントを呼び出してポストを取得
const res = await fetch('https://.../posts')
const posts = await res.json()
// プリレンダリングしたいパスをポストに基づいて取得
const paths = posts.map((post) => ({
params: { id: post.id },
}))
// ビルド時にこれらのパスのみをプリレンダリングします。
// { fallback: false }は、他のルートが404になることを意味します。
return { paths, fallback: false }
}
// これもビルド時に呼び出されます
export async function getStaticProps({ params }) {
// paramsはポストの`id`を含みます。
// ルートが/posts/1の場合、params.idは1です
const res = await fetch(`https://.../posts/${params.id}`)
const post = await res.json()
// propsを介してページにポストデータを渡す
return { props: { post } }
}
export default Postfallback: true
fallbackがtrueの場合、getStaticPropsの動作は以下のように変わります。
getStaticPathsから返されたパスは、ビルド時にgetStaticPropsによってHTMLにレンダリングされます。- ビルド時に生成されていないパスは404ページにはなりません。代わりに、Next.jsはそのようなパスへの最初のリクエストで、ページの「フォールバック」バージョンを提供します。Googleなどのウェブクローラーには、フォールバックは提供されず、代わりにパスは
fallback: 'blocking'のように動作します。 fallback: trueのページがnext/linkまたはnext/router(クライアント側)を経由してナビゲートされる場合、Next.jsはフォールバックを提供せず、代わりにページはfallback: 'blocking'のように動作します。- バックグラウンドで、Next.jsは要求されたパスの
HTMLとJSONを静的に生成します。これにはgetStaticPropsの実行が含まれます。 - 完了すると、ブラウザは生成されたパスの
JSONを受け取ります。これにより、必要なpropsを使用してページが自動的にレンダリングされます。ユーザーの観点からは、ページはフォールバックページから完全なページにスワップされます。 - 同時に、Next.jsはこのパスをプリレンダリング済みページのリストに追加します。同じパスへの後続のリクエストは、ビルド時にプリレンダリングされた他のページと同様に、生成されたページを提供します。
補足:
output: 'export'を使用する場合、fallback: trueはサポートされていません。
fallback: trueはいつ便利ですか?
fallback: trueは、アプリケーションがデータに依存する非常に多数の静的ページを持っている場合に便利です(非常に大きなeコマースサイトなど)。すべての製品ページをプリレンダリングする場合、ビルドに非常に長い時間がかかります。
代わりに、少数のページを静的に生成し、残りのページにfallback: trueを使用できます。まだ生成されていないページがリクエストされた場合、ユーザーはローディングインジケータまたはスケルトンコンポーネント付きのページを表示します。
その直後に、getStaticPropsが完了し、ページは要求されたデータでレンダリングされます。今後、同じページをリクエストするすべてのユーザーは、静的にプリレンダリングされたページを取得します。
これにより、ユーザーは常に高速な体験が保証され、ビルドの高速化と静的生成のメリットが維持されます。
fallback: trueは生成されたページを更新しません。詳細はIncremental Static Regenerationを参照してください。
fallback: 'blocking'
fallbackが'blocking'の場合、getStaticPathsで返されない新しいパスは、SSRと同じようにHTMLが生成されるまで待機し(ここが「blocking」の理由です)、その後は今後のリクエストでキャッシュされるため、パスごとに1回だけ発生します。
getStaticPropsは以下のように動作します。
getStaticPathsから返されたパスは、ビルド時にgetStaticPropsによってHTMLにレンダリングされます。- ビルド時に生成されていないパスは404ページにはなりません。代わりに、Next.jsは最初のリクエストでSSRを実行し、生成された
HTMLを返します。 - 完了すると、ブラウザは生成されたパスの
HTMLを受け取ります。ユーザーの観点からは、「ブラウザがページをリクエスト中」から「完全なページが読み込まれた」へ遷移します。ローディング/フォールバック状態のフラッシュはありません。 - 同時に、Next.jsはこのパスをプリレンダリング済みページのリストに追加します。同じパスへの後続のリクエストは、ビルド時にプリレンダリングされた他のページと同様に、生成されたページを提供します。
fallback: 'blocking'はデフォルトでは生成されたページを更新しません。生成されたページを更新するには、Incremental Static Regenerationをfallback: 'blocking'と併せて使用してください。
補足:
output: 'export'を使用する場合、fallback: 'blocking'はサポートされていません。
フォールバックページ
ページの「フォールバック」バージョンでは、以下が該当します。
- ページのpropsは空になります。
- routerを使用すると、フォールバックがレンダリングされているかどうかを検出できます。
router.isFallbackがtrueになります。
以下の例はisFallbackの使用を示しています。
import { useRouter } from 'next/router'
function Post({ post }) {
const router = useRouter()
// ページがまだ生成されていない場合、これが表示されます
// getStaticProps()が実行完了するまで最初に表示
if (router.isFallback) {
return <div>読み込み中...</div>
}
// ポストをレンダリング...
}
// この関数はビルド時に呼び出されます
export async function getStaticPaths() {
return {
// `/posts/1`と`/posts/2`のみがビルド時に生成されます
paths: [{ params: { id: '1' } }, { params: { id: '2' } }],
// 追加のページを静的に生成できるようにします
// 例:`/posts/3`
fallback: true,
}
}
// これもビルド時に呼び出されます
export async function getStaticProps({ params }) {
// paramsはポストの`id`を含みます。
// ルートが/posts/1の場合、params.idは1です
const res = await fetch(`https://.../posts/${params.id}`)
const post = await res.json()
// propsを介してページにポストデータを渡す
return {
props: { post },
// リクエストが入ってきた場合、最大で1秒に1回ポストを再生成
revalidate: 1,
}
}
export default Postバージョン履歴
| バージョン | 変更内容 |
|---|---|
v13.4.0 | App RouterはgenerateStaticParams()を含む簡素化されたデータ取得と共に安定版になりました |
v12.2.0 | On-Demand Incremental Static Regenerationは安定版です。 |
v12.1.0 | On-Demand Incremental Static Regenerationが追加されました(ベータ版)。 |
v9.5.0 | 安定版のIncremental Static Regeneration |
v9.3.0 | 導入時期:getStaticPaths |