Lang x Lang

getStaticPaths

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

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
}
pages/repo/[name].js
export async function getStaticPaths() {
  return {
    paths: [
      {
        params: {
          name: 'next.js',
        },
      }, // See the "paths" section below
    ],
    fallback: true, // false or "blocking"
  }
}

export async function getStaticProps() {
  const res = await fetch('https://api.github.com/repos/vercel/next.js')
  const repo = await res.json()
  return { props: { repo } }
}

export default function Page({ repo }) {
  return repo.stargazers_count
}

getStaticPaths return values

getStaticPaths関数は、以下の必須プロパティを持つ object を返す必要があります:

paths

pathsキーは、どの paths が事前にレンダリングされるかを決定します。例えば、pages/posts/[id].jsという名前のDynamic Routesを使用するページがあるとします。あなたがこのページからgetStaticPathsを export して、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 はpages/posts/[id].jsのページ component を使用して、next buildの間に/posts/1/posts/2を静的に生成します。

paramsの object の value は、ページ名で使用されているパラメータと一致しなければなりません:

  • ページの名前が pages/posts/[postId]/[commentId] である場合、paramspostIdcommentIdを含むべきです。
  • ページ名がcatch-all routesを使う場合、つまりpages/[...slug]のような形式である場合、paramsslug(配列)を含むべきです。この配列が['hello', 'world']である場合、Next.js は/hello/worldでページを静的に生成します。
  • ページがオプショナルな catch-all routeを使用している場合は、null[]undefined、またはfalseを用いて最もルートの route を render してください。例えば、pages/[[...slug]]に対してslug: falseを提供すると、 Next.js はページ/を静的に生成します。

params 文字列は大文字と小文字を区別します。理想的には、 paths が正しく生成されるように正規化するべきです。例えば、Worldがパラメータに対して返された場合、それはWoRLDが訪れた実際の path と一致するだけで、WoRLDworldでは一致しません。

paramsの object とは別に、i18n が設定されている場合、生成される path の locale を設定するlocaleフィールドが返されることがあります。

fallback: false

fallbackfalseである場合、getStaticPathsによって返されない paths は404 ページが出力されます。

next buildが実行されるとき、Next.js はgetStaticPathsfallback: falseを返したかどうかを確認し、その場合、getStaticPathsによって返された paths のみを build します。このオプションは、作成する paths の number が少ない、または新しいページデータが頻繁に追加されない場合に便利です。もし新たな paths を追加する必要があると分かり、そしてfallback: falseを持っている場合、新しい paths を生成できるように再度next buildを実行する必要があります。

次の例では、pages/posts/[id].jsという 1 ページごとに 1 つのブログの post を事前レンダリングします。ブログの投稿のリストは CMS からフェッチされ、getStaticPathsによって返されます。その後、各ページは CMS から post データをgetStaticPropsを使用してフェッチします。

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

Examples

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

  • getStaticPathsから返される paths は、getStaticPropsによってHTMLへと build 時にレンダリングされます。
  • まだ build 時に生成されていない paths は、404 ページが表示されない結果になります。その代わり、Next.js はそのような path への最初の request で、ページのfallbackversion を提供します。Google などの Web クローラは、fallback が提供されることはなく、代わりに path は、fallback: 'blocking'のように動作します。
  • fallback: trueのページがnext/linknext/router(Client 側)を通じて移動した場合、Next.js は fallback を提供しない代わりに、ページはfallback: 'blocking'のように振る舞います。
  • バックグラウンドで、Next.js は要求された path のHTMLJSONを静的に生成します。これにはgetStaticPropsの実行が含まれます。
  • 完了すると、ブラウザは生成された path のJSONを受信します。これは、必要な props でページを自動的に render するために使用されます。ユーザーの視点からすると、ページは fallback ページからフルページに切り替わります。
  • 同時に、Next.js はこの path を事前レンダリングされたページのリストに追加します。同じ path への後続の Request は、build 時に事前レンダリングされた他のページと同様に、生成されたページを提供します。

Good to know: fallback: trueは、output: 'export'を使用する場合にはサポートされていません。

fallback: trueはいつ役立つのでしょうか?

fallback: trueは、あなたの app がデータに依存する静的ページの number が非常に多い場合(大規模な e-commerce サイトなど)に役立ちます。すべての商品ページを事前にレンダリングしたい場合、build には非常に長い時間がかかります。

それよりも、ページの小さな部分を静的に生成し、残りは fallback: true を使用することができます。まだ生成されていないページを誰かが要求したとき、ユーザーは loading インジケーターや component スケルトンと共にそのページを見ることになります。

その後すぐに、getStaticPropsが完了し、Request されたデータでページがレンダリングされます。これからは、同じページを Request する全ての人が静的に事前レンダリングされたページを取得します。

これにより、ユーザーは常に高速な体験を持つことが保証される一方で、高速な build と Static Generation の利点が保持されます。

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

fallback: 'blocking'

fallback'blocking'の場合、新しい paths は、getStaticPathsによって返されないため、HTMLが生成されるのを待ち、それは SSR (それがblockingである理由)と同じで、その後、将来のリクエストのためにキャッシュされます。そのため、 path ごとに一度だけ起こります。

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

  • getStaticPathsから返される paths は、getStaticPropsによってHTMLへと build 時にレンダリングされます。
  • build 時に生成されていない paths は 404 ページを生じません。代わりに、Next.js は初回の request で SSR を行い、生成されたHTMLを返します。
  • 完了時には、ブラウザは生成された path のHTMLを受け取ります。ユーザーから見ると、"ブラウザがページを要求している"から"フルページがロードされた"へと遷移します。Loading/フォールバックの状態が一瞬表示されることはありません。
  • 同時に、Next.js はこの path を事前レンダリングされたページのリストに追加します。同じ path への後続の Request は、build 時に事前レンダリングされた他のページと同様に、生成されたページを提供します。

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

Good to know: fallback: 'blocking'output: 'export'を使用する際にはサポートされていません。

Fallback ページ

ページの fallback の version では:

  • そのページの props は empty になります。
  • router を使用すると、fallback がレンダリングされているかどうかを検出できます。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

Version History

VersionChanges
v13.4.0App Routerは、generateStaticParams()を含む単純化されたデータフェッチで安定しています
v12.2.0オンデマンド Incremental Static Regenerationは安定しています。
v12.1.0オンデマンド Incremental Static Regeneration追加(ベータ版)。
v9.5.0安定版 Incremental Static Regeneration
v9.3.0getStaticPathsが導入されました。

当社サイトでは、Cookie を使用しています。各規約をご確認の上ご利用ください:
Cookie Policy, Privacy Policy および Terms of Use