getStaticProps

getStaticProps という関数をエクスポートすると、ビルド時にこの関数から返される props を使用してページが事前レンダリングされます:

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
}
export async function getStaticPaths() {
  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
}

getStaticProps で使用するモジュールはトップレベルスコープでインポートできます。インポートされたモジュールはクライアント側にバンドルされません。つまり、データベースからのデータ取得を含むサーバーサイドコードを直接 getStaticProps に記述できます。

context パラメータ

context パラメータは以下のキーを含むオブジェクトです:

名前説明
params動的ルート を使用するページのルートパラメータを含みます。例えば、ページ名が [id].js の場合、params{ id: ... } のようになります。これは後で説明する getStaticPaths と一緒に使用する必要があります。
previewdraftMode で非推奨)ページが プレビューモード にある場合 true、それ以外は false
previewDatadraftMode で非推奨)setPreviewData によって設定された プレビュー データ。
draftModeページが ドラフトモード にある場合 true、それ以外は false
locale有効なロケールが含まれます(有効な場合)。
localesサポートされているすべてのロケールが含まれます(有効な場合)。
defaultLocale設定されたデフォルトロケールが含まれます(有効な場合)。

getStaticProps の戻り値

getStaticProps 関数は propsredirect、または notFound のいずれかを含むオブジェクトを返す必要があり、オプションで revalidate プロパティを追加できます。

props

props オブジェクトはキーと値のペアで、各値はページコンポーネントによって受け取られます。シリアライズ可能なオブジェクトである必要があり、渡されるすべての props は JSON.stringify でシリアライズ可能でなければなりません。

export async function getStaticProps(context) {
  return {
    props: { message: `Next.js is awesome` }, // ページコンポーネントに props として渡されます
  }
}

revalidate

revalidate プロパティは、ページの再生成が可能になるまでの秒数です(デフォルトは false または再検証なし)。

// この関数はビルド時にサーバーサイドで呼び出されます。
// 再検証が有効で新しいリクエストがある場合、
// サーバーレス関数で再度呼び出される可能性があります
export async function getStaticProps() {
  const res = await fetch('https://.../posts')
  const posts = await res.json()

  return {
    props: {
      posts,
    },
    // Next.js はページの再生成を試みます:
    // - リクエストが来たとき
    // - 最大で10秒に1回
    revalidate: 10, // 秒単位
  }
}

増分静的再生成 (ISR) について詳しく学びます。

ISR を利用したページのキャッシュ状態は、x-nextjs-cache レスポンスヘッダーの値を読むことで確認できます。可能な値は以下の通りです:

  • MISS - パスがキャッシュにありません(最初の訪問時に最大1回発生)
  • STALE - パスはキャッシュにありますが、再検証時間を超えているため、バックグラウンドで更新されます
  • HIT - パスはキャッシュにあり、再検証時間を超えていません

notFound

notFound ブール値により、ページは 404 ステータスと 404 ページ を返すことができます。notFound: true の場合、以前に正常に生成されたページがあっても 404 を返します。これは、作者によって削除されたユーザー生成コンテンツなどのユースケースをサポートするためのものです。notFoundここで説明した と同じ revalidate 動作に従います。

export async function getStaticProps(context) {
  const res = await fetch(`https://.../data`)
  const data = await res.json()

  if (!data) {
    return {
      notFound: true,
    }
  }

  return {
    props: { data }, // ページコンポーネントに props として渡されます
  }
}

知っておくと良いこと: fallback: false モードでは notFound は必要ありません。getStaticPaths から返されたパスのみが事前レンダリングされるためです。

redirect

redirect オブジェクトを使用すると、内部または外部リソースにリダイレクトできます。{ destination: string, permanent: boolean } の形式に一致する必要があります。

まれなケースでは、古い HTTP クライアントが適切にリダイレクトするためにカスタムステータスコードを割り当てる必要がある場合があります。このような場合、permanent プロパティの代わりに statusCode プロパティを使用できます(両方は使用できません)。また、next.config.js のリダイレクトと同様に basePath: false を設定できます。

export async function getStaticProps(context) {
  const res = await fetch(`https://...`)
  const data = await res.json()

  if (!data) {
    return {
      redirect: {
        destination: '/',
        permanent: false,
        // statusCode: 301
      },
    }
  }

  return {
    props: { data }, // ページコンポーネントに props として渡されます
  }
}

リダイレクトがビルド時にわかっている場合は、next.config.js に追加する必要があります。

ファイルの読み取り: process.cwd() の使用

getStaticProps でファイルシステムから直接ファイルを読み取ることができます。

そのためには、ファイルへの完全なパスを取得する必要があります。

Next.js はコードを別のディレクトリにコンパイルするため、Pages Router では __dirname を使用できません(返されるパスが異なるため)。

代わりに、Next.js が実行されているディレクトリを提供する process.cwd() を使用できます。

import { promises as fs } from 'fs'
import path from 'path'

// posts は getStaticProps() によってビルド時に設定されます
function Blog({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li>
          <h3>{post.filename}</h3>
          <p>{post.content}</p>
        </li>
      ))}
    </ul>
  )
}

// この関数はビルド時にサーバーサイドで呼び出されます。
// クライアントサイドでは呼び出されないため、
// 直接データベースクエリを実行することもできます。
export async function getStaticProps() {
  const postsDirectory = path.join(process.cwd(), 'posts')
  const filenames = await fs.readdir(postsDirectory)

  const posts = filenames.map(async (filename) => {
    const filePath = path.join(postsDirectory, filename)
    const fileContents = await fs.readFile(filePath, 'utf8')

    // 一般的にはコンテンツを解析/変換します
    // 例えば、ここでマークダウンをHTMLに変換できます

    return {
      filename,
      content: fileContents,
    }
  })
  // { props: { posts } } を返すことで、Blog コンポーネントは
  // ビルド時に `posts` を props として受け取ります
  return {
    props: {
      posts: await Promise.all(posts),
    },
  }
}

export default Blog

バージョン履歴

バージョン変更点
v13.4.0App Router が安定版になり、データ取得が簡素化されました
v12.2.0オンデマンド増分静的再生成 が安定版になりました
v12.1.0オンデマンド増分静的再生成 が追加されました(ベータ)
v10.0.0localelocalesdefaultLocalenotFound オプションが追加されました
v10.0.0fallback: 'blocking' 戻り値オプションが追加されました
v9.5.0安定版 増分静的再生成
v9.3.0getStaticProps が導入されました