😽

ISR (Incremental Static Regeneration) とは? そのメリットとリスク、実装方法まで

2024/10/29に公開

はじめに

ISR (Incremental Static Regeneration) は、Next.js のページ生成手法の一つです。従来の静的サイト生成(SSG)やサーバーサイドレンダリング(SSR)の良いところを組み合わせて、パフォーマンスと最新のコンテンツの提供を両立させるための仕組みです。この記事では、ISR とは何か、その利点、そしてどのように実装するかを解説します。

ISRとは?

ISR は、ビルド時に生成される静的ページの一部を動的に更新できる仕組みです。具体的には、ページのリクエストが発生する度に、バックグラウンドで指定した期限が切れたページを新しいものに差し替えることで、静的サイトのパフォーマンスを維持しつつ、最新のコンテンツを提供します。

例えば、通常の SSG では全てのページがビルド時に生成されるため、ページ数が多いとビルド時間が非常に長くなります。また、ページ内容の更新があった場合は再度全てのページをビルドし直す必要があります。一方でISR を利用すると、必要なタイミングで必要なページだけを更新できるため、ビルド時間が短縮され、ユーザーには常に最新の情報を提供することが可能です。

ISRの利点

  • パフォーマンスの向上

  • 一度生成された静的ページはキャッシュされるため、高速なレスポンスが可能です。

  • ビルド時間が短縮されるので、頻繁にコンテンツが変わるサイトでもスムーズに運用できます。

  • リアルタイム性の向上

    • ページが更新された場合、指定した期限が切れたタイミングで最新のページを生成し、それを配信します。
    • ユーザーがリクエストしたタイミングでバックグラウンドで新しいページを作成するので、リアルタイムに近い情報を提供できます。
  • 運用コストの削減

  • 全てのページを常にビルドし直す必要がないため、リソースの節約につながります。

簡単なISRの実装

Next.jsを用いてISRを実装するにはgetStaticProps 関数を使用して静的ページを生成します。このときに revalidate オプションを設定することで、バックグラウンドで定期的に再生成されるように設定できます。

コード例

// pages/blog/[id].tsx

export const getStaticProps = async (context) => {
    const id = context.params.id;
    const post = await getPostData(id);
    
    return {
        props: {
            post,
        },
        // 60秒ごとにページをバックグラウンドで再生成
        revalidate: 60,
    };
};

// 動的ルーティング用
export const getStaticPaths = async () => {
    const posts = await getAllPostIds();
    
    return {
        paths: posts.map((post) => ({
            params: { id: post.id.toString() },
        })),
        fallback: 'blocking',
    };
};

revalidate オプションの詳細

  • revalidate に設定した秒数が経過すると、そのページは次にリクエストがあったときにバックグラウンドで新しいページが生成されます。
  • 生成された新しいページはキャッシュされ、次回以降のリクエストに利用されます。

ISRの適用例

  • ブログ:新しい記事が投稿されたらすぐに反映されてほしいが、パフォーマンスも重視したい場合。
  • ECサイト:商品の価格や在庫状況など、一定時間ごとに更新される情報を扱う場合。
  • ニュースサイト:常に最新のニュースを表示しつつも、パフォーマンスを重視したい場合。

ISRの短所・リスク

  • 複数のコンテナ間でのキャッシュ同期
    • AWS ECSのようにコンテナベースで分散している環境では、異なるコンテナ(タスク)間でページの再生成が発生する場合、キャッシュが同期されず、一貫性のないデータが表示されるリスクがあります。たとえば、再生成のトリガーが異なるコンテナで発生すると、それぞれで異なるタイミングで新しいコンテンツがキャッシュされ、リクエストごとに異なる内容のページが表示されることがあります。
  • キャッシュの一貫性の問題
    • 分散環境で運用している場合、キャッシュの不整合が発生する可能性があります。例えば、古いコンテナがまだ古いページをキャッシュしている場合、他のコンテナで新しいページが再生成されても、古いデータが提供されることがあります。これにより、ユーザーに不安定な体験をさせるリスクがあります。
  • タイミングの管理が難しい
    • ISRでのページ再生成は、指定したrevalidateの間隔でのみ行われます。このため、特定のイベントが発生した直後に更新したい場合や、更新頻度をきめ細かく管理したい場合には不向きです。また、意図したタイミングでの再生成が難しい場合もあり、特に変更頻度が高いコンテンツを扱う場合には、その設定を慎重に考慮する必要があります。
  • SSRと比較した場合の制約
    • ISRはSSRと違い、期間が切れたページへの初回アクセス時には古いページが提供される可能性があります。つまりバックエンドの状態が即座に反映されるわけではないため、リアルタイム性が求められるケースには適していません。

まとめ

ISR は静的サイトと動的サイトのハイブリッドな手法として、最新の情報を高速に提供するための非常に有用な技術です。
特にページ数が多く、頻繁にコンテンツが更新されるサイトに適しています。Next.js ではISRの設定がシンプルに行えるため、SEOやパフォーマンスを重視したサイトの運用を考えている方は上のリスクのことも含め、ぜひ導入を検討してみてください。

GitHubで編集を提案
nextbeat Tech Blog

Discussion