getServerSideProps

getServerSideProps は、リクエスト時にデータを取得しページのコンテンツをレンダリングするために使用できる Next.js の関数です。

ページコンポーネントから getServerSideProps をエクスポートすることで使用できます。以下の例では、getServerSideProps 内でサードパーティ API からデータを取得し、そのデータを props としてページに渡す方法を示しています:

import type { InferGetServerSidePropsType, GetServerSideProps } from 'next'

type Repo = {
  name: string
  stargazers_count: number
}

export const getServerSideProps = (async () => {
  // 外部APIからデータを取得
  const res = await fetch('https://api.github.com/repos/vercel/next.js')
  const repo: Repo = await res.json()
  // データをpropsとしてページに渡す
  return { props: { repo } }
}) satisfies GetServerSideProps<{ repo: Repo }>

export default function Page({
  repo,
}: InferGetServerSidePropsType<typeof getServerSideProps>) {
  return (
    <main>
      <p>{repo.stargazers_count}</p>
    </main>
  )
}
export async function getServerSideProps() {
  // 外部APIからデータを取得
  const res = await fetch('https://api.github.com/repos/vercel/next.js')
  const repo = await res.json()
  // データをpropsとしてページに渡す
  return { props: { repo } }
}

export default function Page({ repo }) {
  return (
    <main>
      <p>{repo.stargazers_count}</p>
    </main>
  )
}

getServerSideProps を使用するタイミング

パーソナライズされたユーザーデータやリクエスト時のみ知り得る情報(例えば authorization ヘッダーやジオロケーションなど)に依存するページをレンダリングする必要がある場合に getServerSideProps を使用します。

データをリクエスト時に取得する必要がなかったり、データと事前レンダリングされた HTML をキャッシュしたい場合は、getStaticProps の使用を推奨します。

動作仕様

  • getServerSideProps はサーバー上で実行されます
  • getServerSidePropsページ からのみエクスポート可能です
  • getServerSideProps は JSON を返します
  • ユーザーがページにアクセスすると、getServerSideProps がリクエスト時にデータを取得し、そのデータを使用してページの初期 HTML がレンダリングされます
  • ページコンポーネントに渡される props は、初期 HTML の一部としてクライアント側で確認できます。これはページを正しくハイドレートするためです。クライアント側で利用可能にしてはいけない機密情報を props に含めないように注意してください
  • ユーザーが next/link または next/router 経由でページにアクセスすると、Next.js はサーバーに API リクエストを送信し、getServerSideProps が実行されます
  • getServerSideProps はサーバー上で実行されるため、データ取得に Next.js の API Route を呼び出す必要はありません。代わりに、CMS、データベース、その他のサードパーティ API を直接 getServerSideProps 内から呼び出せます

補足:

エラー処理

getServerSideProps 内でエラーが発生すると、pages/500.js ファイルが表示されます。500 ページの作成方法については、500 ページのドキュメントを参照してください。開発中はこのファイルは使用されず、代わりに開発用エラーオーバーレイが表示されます。

エッジケース

Edge ランタイム

getServerSidePropsサーバーレスと Edge ランタイムの両方で使用でき、どちらでも props を設定できます。

ただし、現在 Edge ランタイムではレスポンスオブジェクトにアクセスできません。つまり、例えば getServerSideProps でクッキーを追加することはできません。レスポンスオブジェクトにアクセスする必要がある場合は、デフォルトのランタイムである Node.js ランタイム を引き続き使用する必要があります。

以下のように config を変更することで、ページごとにランタイムを明示的に設定できます:

pages/index.js
export const config = {
  runtime: 'nodejs', // または "edge"
}

export const getServerSideProps = async () => {}

サーバーサイドレンダリング (SSR) でのキャッシュ

getServerSideProps 内でキャッシュヘッダー (Cache-Control) を使用して動的レスポンスをキャッシュできます。例えば、stale-while-revalidate を使用します。

// この値は10秒間新鮮とみなされます (s-maxage=10)。
// 次の10秒以内にリクエストが繰り返されると、以前に
// キャッシュされた値がまだ新鮮な状態で使用されます。59秒前にリクエストが繰り返された場合、
// キャッシュされた値は古くなりますが、依然としてレンダリングされます (stale-while-revalidate=59)。
//
// バックグラウンドで、キャッシュを新しい値で更新するための再検証リクエストが行われます。
// ページを更新すると、新しい値が表示されます。
export async function getServerSideProps({ req, res }) {
  res.setHeader(
    'Cache-Control',
    'public, s-maxage=10, stale-while-revalidate=59'
  )

  return {
    props: {},
  }
}

ただし、cache-control を使用する前に、getStaticPropsISR がユースケースに適しているかどうかを検討することを推奨します。