Next.js初心者の疑問解決!SSG、SSRになる条件って何?【Pages Router】

Featured image of the post

はじめに

Next.jsのSSG、SSR、CSR、ISRについて、初心者のときに最初に知りたかったポイントをまとめる😊

💡
この記事はPages RouterのSSG、SSRについての解説です。
📎
App Router(Next.js13以降)も踏まえたSSG、SSRについてはこちらでも解説しています。

📄 【完全版】Next.jsのSSG、SSR、ISR、CSRを図とコードでスッキリ理解する

この記事で伝えたいこと

どういうページがSSGで、どういうページがSSRになるのか理解する。

さらに具体的なコードの書き方も理解する。

結論

✅デフォルトはSSG。

データの取得の仕方によってはSSRになる。

【前提】SSG、SSRって何?

簡単にSSGとSSRについてまとめる。

💡
すでに知っている人は読み飛ばしてOK!

SSG
  • あらかじめHTMLを作っておく方式。
  • ビルド時にHTMLを作っておくので表示が早い⭕️

    (具体的にはコマンドnpm run buildでビルドした時点でHTMLが生成される。)

  • SSGができるページはSSGがおすすめ。

    (SSGができるページとは、ビルド時でもHTMLに必要なデータが用意できるページ。)

    (会社概要ページなど)

SSR
  • リクエストがきたときにHTMLを作る方式。
  • 毎回HTMLを作るので表示が遅い❌

    (サーバーが毎回頑張ってHTMLを作ってくれる🥲サーバーの負担やばそう🙏)

  • SSGができないページだけSSRを使う。

    (SSGができないページとは、ビルド時ではHTMLに必要なデータが用意できないページ。つまりリクエスト時でないと用意できないデータがある。)

    (例:現在の天気を表示するページなど)

SSG、SSRについてもっと知りたい方はこちら

こちらのサイトが分かりやすかった😊

https://zenn.dev/rinda_1994/articles/e6d8e3150b312d

【疑問】Next.jsにおけるSSG、SSRの決まり方

✅ここからが本題!

背景

Next.jsはページごとにSSG、SSRを変えられるのが便利って聞いた😊

疑問が生まれた

でもページごとにSSG、SSRのどっちになるか、どうやって決まるの?😫

→自分で「このページはSSGだよ!」みたいな宣言をするの?💭

→それとも「こういうページは自動でSSGになる!」みたいな条件があるの?💭

【答え】SSG、SSRになる条件が決まっている
データ取得処理がないページはSSGになる

デフォルトはSSGなので、通常のページは自動的にSSGになる。

データ取得処理があるページはSSG、SSRを選べる

どのようにデータを取得するかでSSG、SSRが決まる。

  • getStaticProps関数でデータ取得するとSSGになる。
  • getServerSideProps関数でデータ取得するとSSRになる。

使い分け

✅前述のとおり、SSGができるページはSSGがおすすめ!

  • ビルド時にHTMLに必要なデータが用意できるページ

    getStaticProps関数でデータ取得する。SSG。

  • リクエスト時でないとデータが用意できないページ(SSGができない)

    getServerSideProps関数でデータ取得する。SSR

【もっと知る】データ取得処理の書き方

getStaticProps関数でデータ取得(SSG)

前述のとおり、getStaticPropsを使ってデータを取得するとSSGになる。

getStaticProps関数のポイント
  • データを取得する処理をする関数。
  • ビルドするときに関数が実行される。
    • 具体的にはビルド時に「関数を実行してデータを取得」→「データを使ってHTMLを生成」。
  • データ取得処理をユーザーに見られることはないのでAPIキーなどが漏洩することはない。
  • リクエスト時はすでに出来上がっているHTMLを返すだけ。(SSG)
  • pageフォルダ内でのみ使用可能。

以下のページはgetStaticProps関数を使っているためSSGになる。

page/MyPage.jsx

// ✅getStaticProps関数でデータを取得する
export async function getStaticProps() {
  // 架空のデータ取得処理
	const res = await fetch(`https://...`)
  const post = await res.json()

  return {
    props: {
      data,
    },
  };
}

// コンポーネントでは取得したデータが使える
function Products({ data }) {
  return (
    <div>
      <h1>Products Page</h1>
      <p>{data}</p>
    </div>
  );
}

export default Products;

【注意】開発環境だとSSGにならない

開発環境ではgetStaticProps関数を使ってもSSGではなく、SSRになるので注意。

💡
開発環境だとSSGが実感できない。

getServerSideProps関数でデータ取得(SSR)

前述のとおり、getServerSidePropsを使ってデータ取得するとSSRになる。

getServerSideProps関数のポイント
  • データを取得する処理をする関数。
  • リクエストがきたときに関数が実行される。
    • 具体的にはリクエスト時に「関数を実行してデータを取得」→「データを使ってHTMLを生成」。(SSR)
  • データ取得処理はサーバー側で実行する。
  • そのためユーザー見られることはないのでAPIキーなどが漏洩することはない。
  • pageフォルダ内でのみ使用可能。

以下のページはgetServerSideProps関数を使っているためSSRになる。

page/MyPage.jsx

// ✅getServerSideProps関数でデータを取得する
export async function getServerSideProps() {
  // 架空のデータ取得処理
	const res = await fetch(`https://...`)
  const post = await res.json()

  return {
    props: {
      data,
    },
  };
}

// コンポーネントでは取得したデータが使える
function Products({ data }) {
  return (
    <div>
      <h1>Products Page</h1>
      <p>{data}</p>
    </div>
  );
}

export default Products;

【発展】動的パスでSSG
先ほどのSSGの方法では動的パスに対応できない

/page/products/[id].jsのようなページは /products/123 /products/xyz など自由にアクセスできてしまう。

つまり[id]に何が入るか不明💦

(ユーザーがアクセスしたときに始めてURLが分かる)

そのためビルド時にファイル名が分からずHTMLを生成することができない。

解決方法

✅getStaticPaths関数を使って、あらかじめどの名前のHTMLファイルを生成するか指定する。

例:「products/1.html」 と 「products/2.html」 を生成する

pages/products/[id].jsx

// ✅事前に生成するHTMLのファイル名を指定する
export async function getStaticPaths() {
	// [id]に何が入るか指定
  const paths = [
    { params: { id: '1' } },  // 必ずparamsの中に入れる。idはファイル名と合わせる。
    { params: { id: '2' } },
  ];

  return {
    paths,
    fallback: false, // id=3など、未知のパスにアクセスすると404を返す
  };
}


// ----------------------------------------------------
// 以降は通常のSSGと同じ

// getStaticProps関数でデータを取得する
export async function getStaticProps() {
  // 架空のデータ取得処理
	const res = await fetch(`https://...`)
  const post = await res.json()

  return {
    props: {
      data,
    },
  };
}

// コンポーネントでは取得したデータが使える
function Products({ data }) {
  return (
    <div>
      <h1>Products Page</h1>
      <p>{data}</p>
    </div>
  );
}

export default Products;

→ビルド時に「products/1.html」 と 「products/2.html」 を生成する。

まとめ

getStaticProps関数 getServerSideProps関数
何をする関数? データを取得する関数 データを取得する関数
いつデータを取得する? ビルド時 リクエスト時
この関数を使うと? SSGになる SSRになる
いつ使えばいい? SSGしたいとき
(ビルド時にデータを取得可能なとき)
SSRしたいとき
(リクエスト時でないとデータ取得できないとき)

参考サイト

全般

SSR

SSG

動的パスのSSG