incremental-static-rendering について
Next.js を使う開発者向けに、サイト全体を再ビルドせず、ページをバックグラウンドで追加・更新する増分静的生成を解説します。
主な機能
- 01バックグラウンドでのページ再生成
- 02新しいルートの遅延生成
- 03時間ベースの再検証
- 04オンデマンド再検証の説明
活用シーン
- 01全体の再ビルドなしでブログ記事を更新
- 02大規模な商品カタログへの対応
- 03コンテンツ変更後のページ更新
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ patternsdev/ skills --skill incremental-static-renderingインストール後、Claude Code で/incremental-static-renderingを入力して読み込まれたか確認します。
詳細
インクリメンタル静的生成
静的生成(SSG)は、SSR と CSR に関する懸念のほとんどに対処できますが、主に静的コンテンツをレンダリングする場合に適しています。レンダリングするコンテンツが動的、または頻繁に変化する場合には制限があります。
複数の投稿がある成長中のブログを考えてみてください。投稿の誤字を修正したいという理由だけで、サイトを再ビルドして再デプロイしたいとは思わないでしょう。同様に、ブログの新しい投稿を1つ追加するたびに、既存のすべてのページを再ビルドする必要もありません。したがって、SSG だけでは大規模なウェブサイトやアプリケーションのレンダリングには不十分です。
使用する場面
- 主に静的なページがあり、全体を再ビルドせずに定期的なデータ更新が必要な場合に使用します
- 変更のたびにすべてのページを再ビルドするのが現実的でない大規模なサイト(ブログ、eコマースなど)に役立ちます
使用しない場面
- コンテンツがリアルタイムで変化し、古いデータが許容されない場合(例:ライブスコア、株価ティッカー)
- ページが完全に動的で、ユーザーごとにパーソナライズされる場合。SSR の方が適しています
- 再検証の期間によって、ユーザーごとに異なるバージョンのコンテンツが表示され、混乱を招く場合
手順
getStaticPropsでrevalidateを使用し、バックグラウンドでページを再生成する時間間隔を設定しますgetStaticPathsでfallback: trueを使用し、初回リクエスト時にページを遅延生成します- コンテンツ変更後すぐに更新するには、オンデマンド再検証(
revalidatePath、revalidateTag)を検討します - Next.js 13+ App Router では、
generateStaticParamsと非同期コンポーネントを使用して ISR を実装します
詳細
インクリメンタル静的生成(iSSG)パターンは、動的データの問題を解決し、頻繁に変化する大量のデータに対して静的サイトをスケールできるように、SSG のアップグレードとして導入されました。iSSG では、ページへの新しいリクエストを受け付けながら、ページの一部をバックグラウンドで事前レンダリングすることで、既存のページを更新したり、新しいページを追加したりできます。
サンプルコード
iSSG は、サイトのビルド後に既存の静的サイトへ段階的に更新を反映するために、次の2つの方法で機能します。
- 新しいページを追加できます
- インクリメンタル静的「再」生成とも呼ばれる、既存のページの更新ができます
新しいページの追加
遅延読み込みの概念を使用して、ビルド後にウェブサイトへ新しいページを追加します。つまり、新しいページは初回リクエスト時にただちに生成されます。生成中は、フロントエンドでフォールバックページや読み込みインジケーターをユーザーに表示できます。
export async function getStaticPaths() {
const products = await getProductsFromDatabase();
const paths = products.map((product) => ({
params: { id: product.id }
}));
// fallback: true means that the missing pages
// will not 404, and instead can render a fallback.
return { paths, fallback: true };
}
// params will contain the id for each generated page.
export async function getStaticProps({ params }) {
return {
props: {
product: await getProductFromDatabase(params.id)
}
}
}
export default function Product({ product }) {
const router = useRouter();
if (router.isFallback) {
return <div>Loading...</div>;
}
// Render product
}
ここでは fallback: true を使用しています。特定の商品に対応するページが利用できない場合は、上記の Product 関数に示すように、読み込みインジケーターなどのフォールバック版ページを表示します。その間に Next.js がバックグラウンドでページを生成します。生成が完了すると、ページはキャッシュされ、フォールバックページの代わりに表示されます。以降の訪問者には、リクエスト時にキャッシュされたページがただちに表示されます。
既存ページの更新
既存のページを再レンダリングするには、ページに適切なタイムアウトを設定します。これにより、設定したタイムアウト期間が経過するたびにページが再検証されます。再検証が完了するまでは、ユーザーには以前のバージョンのページが引き続き表示されます。このように、iSSG は stale-while-revalidate 戦略を使用し、再検証中はキャッシュされた古いバージョンをユーザーに提供します。再検証は全体を再ビルドすることなく、完全にバックグラウンドで行われます。
// This function runs at build time on the build server
export async function getStaticProps() {
return {
props: {
products: await getProductsFromDatabase(),
revalidate: 60, // This will force the page to revalidate after 60 seconds
}
}
}
// The page component receives products prop from getStaticProps at build time
export default function Products({ products }) {
return (
<>
<h1>Products</h1>
<ul>
{products.map((product) => (
<li key={product.id}>{product.name}</li>
))}
</ul>
</>
)
}
60秒後にページを再検証するコードは、getStaticProps() 関数に含まれています。リクエストを受け取ると、まず利用可能な静的ページが提供されます。1分ごとに、静的ページが新しいデータでバックグラウンド更新されます。生成が完了すると、新しいバージョンの静的ファイルが利用可能になり、その後1分間の新しいリクエストに対して提供されます。この機能は Next.js 9.5 以降で利用できます。
利点
iSSG は SSG のすべての利点に加え、さらに次の利点があります。
- 動的データ:サイトを再ビルドすることなく、動的データをサポートできます。
- 速度:データの取得とレンダリングは引き続きバックグラウンドで行われるため、iSSG は少なくとも SSG と同じ速さです。クライアントやサーバーで必要となる処理はほとんどありません。
- 可用性:どのページも、ある程度新しいバージョンが常にオンラインで利用でき、ユーザーがアクセスできます。バックグラウンドでの再生成に失敗しても、古いバージョンは変更されずに残ります。
- 安定性:再生成はサーバー上でページを一度に 1 つずつ行うため、データベースとバックエンドの負荷は低く、パフォーマンスは安定します。その結果、レイテンシーが急増することはありません。
- 配信の容易さ:SSG サイトと同様に、iSSG サイトも、事前レンダリングされたウェブページの配信に使われる CDN のネットワークを通じて配信できます。