コンテンツへスキップ

getStaticProps

ページから`getStaticProps` (静的サイト生成) という関数をエクスポートすると、Next.jsは`getStaticProps`によって返されたpropsを使用して、ビルド時にこのページをプリレンダリングします。

pages/index.tsx
import type { InferGetStaticPropsType, GetStaticProps } from 'next'
 
type Repo = {
  name: string
  stargazers_count: number
}
 
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
}

レンダリングタイプに関係なく、任意の`props`はページコンポーネントに渡され、初期のHTMLでクライアントサイドから閲覧できることに注意してください。これは、ページが正しくハイドレーションされるようにするためです。クライアントで利用可能になるべきではない機密情報が`props`に含まれていないことを確認してください。

`getStaticProps` APIリファレンスには、`getStaticProps`で使用できるすべてのパラメーターとpropsが記載されています。

getStaticPropsはいつ使うべきか?

`getStaticProps`は、以下の場合に使用してください。

  • ページをレンダリングするために必要なデータが、ユーザーのリクエストより前にビルド時に利用可能である
  • データがヘッドレスCMSから取得される
  • ページが(SEOのために)プリレンダリングされる必要があり、非常に高速であること — `getStaticProps`は`HTML`と`JSON`ファイルを生成し、どちらもCDNによってパフォーマンス向上のためにキャッシュできる
  • データが一般にキャッシュ可能である(ユーザー固有ではない)。この条件は、ミドルウェアを使用してパスを書き換えることで、特定の状況で回避できます。

getStaticPropsが実行されるタイミング

`getStaticProps`は常にサーバー上で実行され、クライアント上では決して実行されません。`getStaticProps`内に記述されたコードがクライアントサイドバンドルから削除されることをこのツールで検証できます。

  • `getStaticProps`は常に`next build`中に実行されます。
  • `getStaticProps`は`fallback: true`を使用している場合、バックグラウンドで実行されます。
  • `getStaticProps`は`fallback: blocking`を使用している場合、初期レンダリングの前に呼び出されます。
  • `getStaticProps`は`revalidate`を使用している場合、バックグラウンドで実行されます。
  • `getStaticProps`は`revalidate()`を使用している場合、オンデマンドでバックグラウンドで実行されます。

Incremental Static Regenerationと組み合わせると、`getStaticProps`は古いページが再検証されている間、バックグラウンドで実行され、新しいページがブラウザに提供されます。

`getStaticProps`は静的HTMLを生成するため、着信リクエスト(クエリパラメータやHTTPヘッダーなど)にアクセスできません。ページのリクエストにアクセスする必要がある場合は、`getStaticProps`に加えてMiddlewareの使用を検討してください。

CMSからデータをフェッチするためにgetStaticPropsを使用する

以下の例は、CMSからブログ投稿のリストをフェッチする方法を示しています。

pages/blog.tsx
// posts will be populated at build time by getStaticProps()
export default function Blog({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li>{post.title}</li>
      ))}
    </ul>
  )
}
 
// This function gets called at build time on server-side.
// It won't be called on client-side, so you can even do
// direct database queries.
export async function getStaticProps() {
  // Call an external API endpoint to get posts.
  // You can use any data fetching library
  const res = await fetch('https://.../posts')
  const posts = await res.json()
 
  // By returning { props: { posts } }, the Blog component
  // will receive `posts` as a prop at build time
  return {
    props: {
      posts,
    },
  }
}

`getStaticProps` APIリファレンスには、`getStaticProps`で使用できるすべてのパラメーターとpropsが記載されています。

サーバーサイドコードを直接記述する

`getStaticProps`はサーバーサイドでのみ実行されるため、クライアントサイドで実行されることはありません。ブラウザ用のJSバンドルにも含まれないため、データベースクエリをブラウザに送信することなく直接記述できます。

つまり、`getStaticProps`から(それ自体が外部ソースからデータをフェッチする)**APIルート**をフェッチする代わりに、サーバーサイドコードを`getStaticProps`に直接記述できます。

以下の例を考えてみましょう。APIルートはCMSからデータをフェッチするために使用されます。そのAPIルートは`getStaticProps`から直接呼び出されます。これにより、余分な呼び出しが発生し、パフォーマンスが低下します。代わりに、CMSからデータをフェッチするロジックは、`lib/`ディレクトリを使用して共有できます。その後、`getStaticProps`と共有できます。

lib/load-posts.js
// The following function is shared
// with getStaticProps and API routes
// from a `lib/` directory
export async function loadPosts() {
  // Call an external API endpoint to get posts
  const res = await fetch('https://.../posts/')
  const data = await res.json()
 
  return data
}
pages/blog.js
// pages/blog.js
import { loadPosts } from '../lib/load-posts'
 
// This function runs only on the server side
export async function getStaticProps() {
  // Instead of fetching your `/api` route you can call the same
  // function directly in `getStaticProps`
  const posts = await loadPosts()
 
  // Props returned will be passed to the page component
  return { props: { posts } }
}

あるいは、APIルートを使ってデータを取得**しない**場合は、`fetch()` APIを`getStaticProps`で直接使ってデータを取得することも**できます**。

Next.jsがクライアントサイドバンドルから何を削除するかを確認するには、next-code-eliminationツールを使用できます。

HTMLとJSONの両方を静的に生成する

`getStaticProps`を持つページがビルド時にプリレンダリングされると、ページのHTMLファイルに加えて、Next.jsは`getStaticProps`の実行結果を保持するJSONファイルを生成します。

このJSONファイルは、`next/link`または`next/router`を介したクライアントサイドルーティングで使用されます。`getStaticProps`を使用してプリレンダリングされたページに移動すると、Next.jsはこのJSONファイル(ビルド時に事前に計算されたもの)をフェッチし、それをページコンポーネントのpropsとして使用します。つまり、クライアントサイドのページ遷移では、エクスポートされたJSONのみが使用されるため、`getStaticProps`は**呼び出されません**。

Incremental Static Generationを使用する場合、クライアントサイドナビゲーションに必要なJSONを生成するために、`getStaticProps`はバックグラウンドで実行されます。同じページに対して複数のリクエストが行われる形でこれが見られるかもしれませんが、これは意図された動作であり、エンドユーザーのパフォーマンスには影響しません。

getStaticPropsはどこで使えるか

`getStaticProps`は**ページ**からのみエクスポートできます。非ページファイル、`_app`、`_document`、または`_error`からはエクスポート**できません**。

この制限の理由の一つは、Reactがページがレンダリングされる前に必要なすべてのデータを持っている必要があるためです。

また、`getStaticProps`は単独の関数としてエクスポートする必要があります — ページコンポーネントのプロパティとして`getStaticProps`を追加しても**動作しません**。

知っておくと便利です: カスタムアプリを作成した場合、リンク先のドキュメントに示されているように`pageProps`をページコンポーネントに渡していることを確認してください。そうしないとpropsは空になります。

開発環境ではすべてのリクエストで実行される

開発環境 (`next dev`) では、`getStaticProps`はすべてのリクエストで呼び出されます。

プレビューモード

プレビューモードを使用すると、ビルド時ではなく、一時的に静的生成をバイパスしてリクエスト時にページをレンダリングできます。たとえば、ヘッドレスCMSを使用している場合、公開前に下書きをプレビューしたい場合などです。