Menu

getStaticPaths

Dynamic Routesを使用するページからgetStaticPathsという名前の関数をエクスポートすると、Next.jsはgetStaticPathsで指定されたすべてのパスを静的にプリレンダリングします。

pages/repo/[name].tsx
TypeScript
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]の場合、paramspostIdcommentIdを含む必要があります。
  • ページ名がpages/[...slug]のようなcatch-all routesを使用する場合、paramsslugを含む必要があります(配列です)。この配列が['hello', 'world']の場合、Next.jsは/hello/worldでページを静的に生成します。
  • ページがoptional catch-all routeを使用する場合、null[]undefined、またはfalseを使用してルート最上位のルートをレンダリングします。例えば、pages/[[...slug]]slug: falseを指定すると、Next.jsは/でページを静的に生成します。

params文字列は大文字と小文字を区別し、パスが正しく生成されるように正規化することが理想的です。例えば、paramsWoRLDが返される場合、実際に訪問されるパスがWoRLDの場合にのみマッチし、worldWorldにはマッチしません。

paramsオブジェクトとは別に、i18nが設定されている場合はlocaleフィールドを返すことができます。これにより、生成されるパスのロケールが設定されます。

fallback: false

fallbackfalseの場合、getStaticPathsで返されないパスは404ページになります。

next buildが実行されると、Next.jsはgetStaticPathsfallback: falseを返しているかを確認し、getStaticPathsで返されたパスのみをビルドします。このオプションは、作成するパスの数が少ない場合、または新しいページデータが頻繁に追加されない場合に便利です。より多くのパスを追加する必要があり、fallback: falseを設定している場合は、新しいパスが生成されるようにnext buildを再度実行する必要があります。

以下の例は、pages/posts/[id].jsという名前のページごとに1つのブログ記事をプリレンダリングしています。ブログ記事のリストはCMSから取得され、getStaticPathsで返されます。その後、各ページについて、getStaticPropsを使用してCMSからポストデータを取得します。

pages/posts/[id].js
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 Post

fallback: true

fallbacktrueの場合、getStaticPropsの動作は以下のように変わります。

  • getStaticPathsから返されたパスは、ビルド時にgetStaticPropsによってHTMLにレンダリングされます。
  • ビルド時に生成されていないパスは404ページにはなりません。代わりに、Next.jsはそのようなパスへの最初のリクエストで、ページの「フォールバック」バージョンを提供します。Googleなどのウェブクローラーには、フォールバックは提供されず、代わりにパスはfallback: 'blocking'のように動作します。
  • fallback: trueのページがnext/linkまたはnext/router(クライアント側)を経由してナビゲートされる場合、Next.jsはフォールバックを提供せず、代わりにページはfallback: 'blocking'のように動作します。
  • バックグラウンドで、Next.jsは要求されたパスのHTMLJSONを静的に生成します。これには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 Regenerationfallback: 'blocking'と併せて使用してください。

補足output: 'export'を使用する場合、fallback: 'blocking'はサポートされていません。

フォールバックページ

ページの「フォールバック」バージョンでは、以下が該当します。

  • ページのpropsは空になります。
  • routerを使用すると、フォールバックがレンダリングされているかどうかを検出できます。router.isFallbacktrueになります。

以下の例はisFallbackの使用を示しています。

pages/posts/[id].js
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.0App RoutergenerateStaticParams()を含む簡素化されたデータ取得と共に安定版になりました
v12.2.0On-Demand Incremental Static Regenerationは安定版です。
v12.1.0On-Demand Incremental Static Regenerationが追加されました(ベータ版)。
v9.5.0安定版のIncremental Static Regeneration
v9.3.0導入時期:getStaticPaths