📚

Next.jsでISR(getStaticProps)を動的ページで使用する方法

2023/05/15に公開

商品詳細ページなど、IDによって動的にURLが決まるページにISR(getStaticProps)を使用する方法を紹介します。

  • URL例
/item_detail/1

ISR(Incremental Static Regeneration)とは

Next.js の ISR (Incremental Static Regeneration) は、静的なウェブサイトを動的に更新するための機能です。これにより、事前ビルドされた静的ページを動的に再生成することができます。

従来の静的サイトジェネレーターでは、サイトを事前ビルドし、生成されたファイルをサーバーにデプロイする必要がありました。しかし、Next.js の ISR では、あらかじめ生成された静的ページをキャッシュし、ユーザーがページにアクセスするときに再生成することができます。

ISR は、静的サイトに一定時間の更新時間を設定することでキャッシュを自動更新するようになっているため、動的なページを高速に表示することができるようになります。

Next.jsのISRで動的コンテンツをキャッシュするときの戦略

pagesのファイル構成

pages
  └ item_detail
      └ [id].tsx

[id].tsxのソース

[id].tsx
export const ItemDetailPage = (props: any) => {
  return <div>{props.data.item_code} : {props.data.item_name}</div>
}

export const getStaticProps = async ({ params }: any) => {
  const data = await getPost(params.id)
  return {
    props: {
      data: data
    },
    revalidate: 30
  }
}

export const getStaticPaths = async () => {
  const list = (await getPosts()) || []
  const paths = list.map((_data: any) => {
    return {
      params: { id: _data.item_code }
    }
  })
  return {
    paths: paths,
    fallback: 'blocking'
  }
}

export default ItemDetailPage

getStaticPropsとは

Next.js で使用される関数の1つで、SSG (静的サイトジェネレーション) に使用されます。この関数は、ページのデータを取得するために使用されます。ページコンポーネントが描画される前に、この関数が実行され、ページに必要なデータを取得します。

ページコンポーネントに props を提供することができます。これにより、ページのデータを取得し、ページの HTML を生成する際に使用することができます。この関数が返すオブジェクトは、ページの props としてコンポーネントに渡されます。

export const getStaticProps = async ({ params }: any) => {
  // パラメータに応じた商品データの取得
  const data = await getPost(params.id)
  return {
    props: {
      // このデータをpropsとしてpageコンポーネントに渡すことができる
      data: data
    }
  }
}

ページのコンテキストを含めることができるため、動的なパラメーターに基づいてページを生成することができます。これにより、動的なページを静的に生成することができ、高速なページの読み込みを実現することができます。

revalidateを設定することでISRになる

SSGにキャッシュの更新時間(revalidate)を設定することでISRにすることができます。

  return {
    props: {
      data: data
    },
+   revalidate: 30 // 30秒ごとにキャッシュを更新する
  }

30秒ごとにgetPostを実行し、ページを更新します。

getStaticPathsとは

Next.js で使用される関数の1つで、動的なルーティングを実現するために使用されます。この関数は、動的なパラメーターを含むページのパスを事前に生成し、静的ファイルとしてビルドするために使用されます。

getStaticPathsの例
export const getStaticPaths = async () => {
  return {
    paths: [{
      params: { id: 1 }
    },{
      params: { id: 2 }
    }],
    fallback: 'blocking'
  }
}
ビルドされるページ
pages
  └ item_detail
      │ 1.html2.html

しかし、動的ページはあくまでも商品コードやユニークなIDをページURLに指定することが多いので、params.idを動的に設定する必要があります。

ここをデータストアからfetchなどで商品情報の一覧データを取得して、mapでループし設定します。

export const getStaticPaths = async () => {
+ const list = (await getPosts()) || []
+ const paths = list.map((_data: any) => {
+   return {
+     params: { id: _data.item_code } // 動的にidを設定する
+   }
+ })
 return {
-   paths: [{
-     params: { id: 1 }
-   },{
-     params: { id: 2 }
-   }],
+   paths: paths,
    fallback: 'blocking'
  }
}

getStaticPaths 関数は、[param] のような動的なパスを持つページのコンポーネントで使用されます。この関数は、可能な動的なパスのリストを生成するために使用されます。動的なパスを含むページがビルドされる前に、この関数が実行されます。

fallback オプション

fallback オプションを指定することができます。このオプションは、Next.js が動的なパラメーターを持つページにアクセスした場合にどのように応答するかを決定します。fallback オプションが指定されていない場合、Next.js は存在しない動的なパラメーターのページにアクセスした場合に 404 エラーを返します。fallback オプションが指定されている場合、Next.js は動的なページの HTML を動的に生成します。

ISRは認証情報が必要なページでは動作できない

SSG もしくは ISR はデプロイ時にページを生成する性質上、認証が必要なデータをgetStaticProps内で取得することができないので気をつけてください。

NG例
export const getStaticProps = async ({ params }: any) => {
  // 認証が必要な情報を取得するAPIはエラーが発生しビルドできない
  const data = await getPostInLoginUser(params.id)
  return {
    props: {
      data: data
    },
    revalidate: 30
  }
}

一般的に商品一覧や商品詳細は会員でなくても(認証情報が必要なくても)閲覧可能にすることがほとんどです。そういった場合、この ISR を採用するとこで高速にページを表示することができます。

認証情報が必要なデータを取得し表示する場合(主に会員ページなど)は SSG でjavascriptによるデータフェッチを行うか、SSR(Server Side Rendering)を採用することをおすすめします。

Discussion