コンテンツにスキップ

getStaticPaths

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

pages/repo/[name].tsx
import type {
  InferGetStaticPropsType,
  GetStaticProps,
  GetStaticPaths,
} from 'next'
 
type Repo = {
  name: string
  stargazers_count: number
}
 
export const getStaticPaths = (async () => {
  return {
    paths: [
      {
        params: {
          name: 'next.js',
        },
      }, // See the "paths" section below
    ],
    fallback: true, // false or "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' },
      // with i18n configured the locale for the path can be returned as well
      locale: "en",
    },
  ],
  fallback: ...
}

Next.jsはnext build中に、pages/posts/[id].jsのページコンポーネントを使用して、/posts/1/posts/2を静的に生成します。

paramsオブジェクトの値は、ページ名で使用されているパラメータと一致している必要があります。

  • ページ名がpages/posts/[postId]/[commentId]の場合、paramsにはpostIdcommentIdが含まれている必要があります。
  • ページ名が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文字列は大文字小文字を区別し、パスが正しく生成されるように正規化することが理想的です。たとえば、パラメータとしてWoRLDが返された場合、worldWorldではなく、実際のパスがWoRLDである場合にのみ一致します。

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 }) {
  // Render post...
}
 
// This function gets called at build time
export async function getStaticPaths() {
  // Call an external API endpoint to get posts
  const res = await fetch('https://.../posts')
  const posts = await res.json()
 
  // Get the paths we want to pre-render based on posts
  const paths = posts.map((post) => ({
    params: { id: post.id },
  }))
 
  // We'll pre-render only these paths at build time.
  // { fallback: false } means other routes should 404.
  return { paths, fallback: false }
}
 
// This also gets called at build time
export async function getStaticProps({ params }) {
  // params contains the post `id`.
  // If the route is like /posts/1, then params.id is 1
  const res = await fetch(`https://.../posts/${params.id}`)
  const post = await res.json()
 
  // Pass post data to the page via props
  return { props: { post } }
}
 
export default Post

fallback: true

fallbacktrueの場合、getStaticPropsの動作は次のように変更されます。

  • getStaticPathsから返されたパスは、getStaticPropsによってビルド時にHTMLにレンダリングされます。
  • ビルド時に生成されなかったパスは404ページになりません。代わりに、Next.jsはそのようなパスへの最初の要求時にページの「フォールバック」バージョンを提供します。GoogleなどのWebクローラーにはフォールバックは提供されず、代わりにパスはfallback: 'blocking'の場合と同様に動作します。
  • fallback: trueを持つページがnext/linkまたはnext/router(クライアントサイド)経由でナビゲートされた場合、Next.jsはフォールバックを提供せず、代わりにページはfallback: 'blocking'と同様に動作します。
  • バックグラウンドで、Next.jsは要求されたパスのHTMLJSONを静的に生成します。これにはgetStaticPropsの実行が含まれます。
  • 完了すると、ブラウザは生成されたパスのJSONを受け取ります。これは、必要なpropsでページを自動的にレンダリングするために使用されます。ユーザーの視点からは、ページはフォールバックページから完全なページに切り替わります。
  • 同時に、Next.jsはこのパスを事前レンダリングされたページのリストに追加します。同じパスへの後続の要求は、ビルド時に事前レンダリングされた他のページと同様に、生成されたページを提供します。

知っておくと良いことfallback: trueは、output: 'export'を使用している場合はサポートされていません。

fallback: trueはどのような場合に便利ですか?

fallback: trueは、アプリにデータに依存する非常に多数の静的ページがある場合(大規模なeコマースサイトなど)に便利です。すべての製品ページを事前レンダリングしたい場合、ビルドに非常に時間がかかります。

代わりに、少数のページのみを静的に生成し、残りはfallback: trueを使用することができます。まだ生成されていないページがリクエストされると、ユーザーにはローディングインジケーターまたはスケルトンコンポーネントが表示されます。

まもなく、getStaticPropsが完了し、ページが要求されたデータでレンダリングされます。今後、同じページをリクエストするすべての人に、静的に事前レンダリングされたページが提供されます。

これにより、ユーザーは常に高速なエクスペリエンスを得られ、ビルドの高速性と静的生成の利点を維持できます。

fallback: trueは生成されたページを更新しません。更新については、Incremental Static Regenerationを参照してください。

fallback: 'blocking'

fallback'blocking'の場合、getStaticPathsで返されない新しいパスは、HTMLが生成されるまで待機します(SSRと同様に、そのため「blocking」と呼ばれます)。その後、将来の要求のためにキャッシュされるため、パスごとに1回のみ発生します。

getStaticPropsは次のように動作します。

  • getStaticPathsから返されたパスは、getStaticPropsによってビルド時にHTMLにレンダリングされます。
  • ビルド時に生成されなかったパスは404ページになりません。代わりに、Next.jsは最初の要求時にSSRを実行し、生成されたHTMLを返します。
  • 完了すると、ブラウザは生成されたパスのHTMLを受け取ります。ユーザーの視点からは、「ブラウザがページを要求している」状態から「完全なページが読み込まれた」状態に移行します。ローディング/フォールバック状態のフラッシュはありません。
  • 同時に、Next.jsはこのパスを事前レンダリングされたページのリストに追加します。同じパスへの後続の要求は、ビルド時に事前レンダリングされた他のページと同様に、生成されたページを提供します。

fallback: 'blocking'はデフォルトでは生成されたページを更新しません。生成されたページを更新するには、fallback: 'blocking'と組み合わせてIncremental Static Regenerationを使用してください。

知っておくと良いことfallback: 'blocking'は、output: 'export'を使用している場合はサポートされていません。

フォールバックページ

「フォールバック」バージョンのページでは

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

次の例は、isFallbackの使用方法を示しています。

pages/posts/[id].js
import { useRouter } from 'next/router'
 
function Post({ post }) {
  const router = useRouter()
 
  // If the page is not yet generated, this will be displayed
  // initially until getStaticProps() finishes running
  if (router.isFallback) {
    return <div>Loading...</div>
  }
 
  // Render post...
}
 
// This function gets called at build time
export async function getStaticPaths() {
  return {
    // Only `/posts/1` and `/posts/2` are generated at build time
    paths: [{ params: { id: '1' } }, { params: { id: '2' } }],
    // Enable statically generating additional pages
    // For example: `/posts/3`
    fallback: true,
  }
}
 
// This also gets called at build time
export async function getStaticProps({ params }) {
  // params contains the post `id`.
  // If the route is like /posts/1, then params.id is 1
  const res = await fetch(`https://.../posts/${params.id}`)
  const post = await res.json()
 
  // Pass post data to the page via props
  return {
    props: { post },
    // Re-generate the post at most once per second
    // if a request comes in
    revalidate: 1,
  }
}
 
export default Post

バージョン履歴

バージョン変更履歴
v13.4.0App Routerは、generateStaticParams()を含む、簡略化されたデータ取得で安定しました。
v12.2.0オンデマンドでのIncremental Static Regeneration(On-Demand Incremental Static Regeneration)が安定しました。
v12.1.0オンデマンドでのIncremental Static Regeneration(On-Demand Incremental Static Regeneration)が追加されました(ベータ版)。
v9.5.0安定したIncremental Static Regeneration
v9.3.0getStaticPathsが導入されました。