Menu

getStaticPaths

動的ルートを使用するページから 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',
        },
      }, // 「パス」セクションを参照
    ],
    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 という動的ルートを使用するページがあるとします。このページから 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 には postIdcommentId が含まれる必要があります。
  • ページ名が キャッチオールルートpages/[...slug] など)を使用している場合、params には slug(配列)が含まれる必要があります。この配列が ['hello', 'world'] の場合、Next.jsは /hello/world のページを静的に生成します。
  • オプションのキャッチオールルートを使用する場合、ルート最上位のページをレンダリングするために 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 }) {
  // 投稿をレンダリング...
}
 
// この関数はビルド時に呼び出されます
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()
 
  // プロップスを介してページに投稿データを渡します
  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 を受け取ります。これは、必要なプロップスを使用してページを自動的にレンダリングするために使用されます。ユーザーの視点からは、ページがフォールバックページから完全なページに入れ替わります。
  • 同時に、Next.jsはこのパスをプリレンダリングされたページのリストに追加します。同じパスへのその後のリクエストは、ビルド時にプリレンダリングされた他のページと同様に、生成されたページを提供します。

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

fallback: true が有用な場合

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

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

その後すぐに、getStaticProps が完了し、ページは要求されたデータでレンダリングされます。今後、同じページをリクエストする人は、静的にプリレンダリングされたページを取得します。

これにより、ユーザーは静的生成の利点と高速なビルドを維持しながら、常に高速な体験を実現できます。

fallback: true は生成されたページを 更新 しません。そのためには、増分静的再生成を参照してください。

fallback: 'blocking'

fallback'blocking' の場合、getStaticPaths によって返されなかった新しいパスは、HTML の生成を待ち(そのため blocking)、SSRと同一の動作をし、その後、将来のリクエストのためにキャッシュされるため、パスごとに1回のみ発生します。

getStaticProps は以下のように動作します:

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

fallback: 'blocking' は、デフォルトでは生成されたページを 更新 しません。生成されたページを更新するには、増分静的再生成fallback: 'blocking' と併用してください。

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

フォールバックページ

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

  • ページのpropsは空になります。
  • ルーターを使用することで、フォールバックがレンダリングされているかを検出できます。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 Router が安定版となり、generateStaticParams() を含むデータ取得が簡素化されました
v12.2.0オンデマンド増分静的再生成 が安定版になりました。
v12.1.0オンデマンド増分静的再生成 が追加されました(ベータ版)。
v9.5.0安定版 増分静的再生成
v9.3.0getStaticPaths が導入されました。