インクリメンタル静的再生成(ISR)の実装方法
インクリメンタル静的再生成(ISR)により、サイト全体を再構築することなく静的コンテンツを更新できます。
- サイト全体を再構築することなく静的コンテンツを更新できます
- ほとんどのリクエストで事前レンダリングされた静的ページを配信することで、サーバー負荷を軽減します
cache-controlヘッダーがページに自動的に追加されることを保証しますnext buildに時間がかかることなく、大量のコンテンツページを処理します
最小限の例を以下に示します
interface Post {
id: string
title: string
content: string
}
// Next.js will invalidate the cache when a
// request comes in, at most once every 60 seconds.
export const revalidate = 60
export async function generateStaticParams() {
const posts: Post[] = await fetch('https://api.vercel.app/blog').then((res) =>
res.json()
)
return posts.map((post) => ({
id: String(post.id),
}))
}
export default async function Page({
params,
}: {
params: Promise<{ id: string }>
}) {
const { id } = await params
const post: Post = await fetch(`https://api.vercel.app/blog/${id}`).then(
(res) => res.json()
)
return (
<main>
<h1>{post.title}</h1>
<p>{post.content}</p>
</main>
)
}この例がどのように機能するか
next build中に、すべての既知のブログ投稿が生成されます- これらのページへのすべてリクエスト(例:
/blog/1)はキャッシュされ、瞬時に応答します - 60秒経過後も、次回の要求はキャッシュされた(古い)ページを返します
- キャッシュが無効化され、ページの新しいバージョンがバックグラウンドで生成され始めます
- 正常に生成されると、次回の要求で更新されたページが返され、それ以降のリクエストのためにキャッシュされます
/blog/26がリクエストされ、それが存在する場合、ページはオンデマンドで生成されます。この動作は、異なるdynamicParams値を使用することで変更できます。ただし、投稿が存在しない場合は 404 が返されます。
リファレンス
ルートセグメント設定
関数
例
時間ベースの再検証
これは /blog でブログ投稿のリストを取得して表示します。1 時間経過すると、次の訪問者もキャッシュされた(古い)バージョンのページをすぐに受け取り、高速な応答が得られます。同時に、Next.js はバックグラウンドで新しいバージョンの生成をトリガーします。新しいバージョンが正常に生成されると、キャッシュされたバージョンが置き換えられ、後続の訪問者は更新されたコンテンツを受け取ります。
interface Post {
id: string
title: string
content: string
}
export const revalidate = 3600 // invalidate every hour
export default async function Page() {
const data = await fetch('https://api.vercel.app/blog')
const posts: Post[] = await data.json()
return (
<main>
<h1>Blog Posts</h1>
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</main>
)
}再検証時間には、1 秒ではなく 1 時間のような高い値を設定することをお勧めします。より正確な制御が必要な場合は、オンデマンド再検証を検討してください。リアルタイムデータが必要な場合は、動的レンダリングへの切り替えを検討してください。
revalidatePath によるオンデマンド再検証
より正確な再検証方法として、revalidatePath 関数を使用してキャッシュされたページをオンデマンドで無効化します。
たとえば、この Server Action は新しい投稿が追加された後に呼び出されます。Server Component でデータを取得する方法に関わらず、fetch を使用するか、データベースに接続するかに関わらず、これはルート全体のキャッシュを無効化します。そのルートへの次回の要求は再生成をトリガーし、新しいデータを配信し、後続のリクエストのためにキャッシュされます。
注意:
revalidatePathはキャッシュエントリを無効化しますが、生成は次回の要求時に行われます。次回の要求を待たずにキャッシュエントリをすぐに再生成したい場合は、Pages Router のres.revalidateメソッドを使用できます。App Router で積極的な再生成機能を提供する新しいメソッドの追加に取り組んでいます。
'use server'
import { revalidatePath } from 'next/cache'
export async function createPost() {
// Invalidate the cache for the /posts route
revalidatePath('/posts')
}revalidateTag によるオンデマンド再検証
ほとんどのユースケースでは、パス全体を再検証することを推奨します。より詳細な制御が必要な場合は、revalidateTag 関数を使用できます。たとえば、個々の fetch 呼び出しにタグを付けることができます。
export default async function Page() {
const data = await fetch('https://api.vercel.app/blog', {
next: { tags: ['posts'] },
})
const posts = await data.json()
// ...
}ORM を使用している場合、またはデータベースに接続している場合は、unstable_cache を使用できます。
import { unstable_cache } from 'next/cache'
import { db, posts } from '@/lib/db'
const getCachedPosts = unstable_cache(
async () => {
return await db.select().from(posts)
},
['posts'],
{ revalidate: 3600, tags: ['posts'] }
)
export default async function Page() {
const posts = getCachedPosts()
// ...
}次に、Server Actions または Route Handler で revalidateTag を使用できます。
'use server'
import { revalidateTag } from 'next/cache'
export async function createPost() {
// Invalidate all data tagged with 'posts'
revalidateTag('posts')
}キャッチされない例外の処理
データ再検証の試行中にエラーが発生した場合、最後に正常に生成されたデータはキャッシュから提供され続けます。次回の subsequent リクエストで、Next.js はデータの再検証を再試行します。エラー処理についてさらに詳しく。
キャッシュ場所のカスタマイズ
キャッシュされたページとデータを永続ストレージに保持したい場合、または Next.js アプリケーションの複数のコンテナまたはインスタンス間でキャッシュを共有したい場合は、Next.js のキャッシュ場所を構成できます。さらに詳しく。
トラブルシューティング
ローカル開発でのキャッシュデータのデバッグ
fetch API を使用している場合、どのリクエストがキャッシュされているか、またはされていないかを理解するために、追加のロギングを追加できます。logging オプションについてさらに詳しく。
module.exports = {
logging: {
fetches: {
fullUrl: true,
},
},
}本番環境での正しい動作の検証
本番環境でページが正しくキャッシュされ、再検証されていることを確認するには、next build を実行してから next start を実行して本番 Next.js サーバーを実行することで、ローカルでテストできます。
これにより、本番環境での ISR の動作をテストできます。さらにデバッグするには、.env ファイルに次の環境変数を追加します。
NEXT_PRIVATE_DEBUG_CACHE=1これにより、Next.js サーバーコンソールに ISR のキャッシュヒットとミスのログが出力されます。出力を検査して、next build 中にどのページが生成されるか、またオンデマンドでパスがアクセスされたときにページがどのように更新されるかを確認できます。
注意点
- ISR は、Node.js ランタイム(デフォルト)を使用している場合にのみサポートされます。
- 静的エクスポートを作成する際には ISR はサポートされません。静的エクスポート。
- 静的レンダリングされたルートで複数の
fetchリクエストがあり、それぞれ異なるrevalidate周波数の場合、最も低い時間が ISR に使用されます。ただし、それらのrevalidate周波数は、データキャッシュによって引き続き尊重されます。 - ルートで使用されている
fetchリクエストのいずれかにrevalidate時間が0であるか、明示的なno-storeが指定されている場合、ルートは動的にレンダリングされます。 - プロキシはオンデマンド ISR リクエストでは実行されないため、プロキシ内のパス書き換えやロジックは適用されません。正確なパスを再検証していることを確認してください。たとえば、書き換えられた
/post-1ではなく、/post/1です。
プラットフォームのサポート
| デプロイメントオプション | サポート |
|---|---|
| Node.jsサーバー | はい |
| Dockerコンテナ | はい |
| 静的エクスポート | いいえ |
| アダプター | プラットフォーム固有 |
Next.js をセルフホスティングする際に ISR を構成する方法については、こちらをご覧ください。
バージョン履歴
| バージョン | 変更履歴 |
|---|---|
v14.1.0 | カスタム cacheHandler は安定しています。 |
v13.0.0 | App Router が導入されました。 |
v12.2.0 | Pages Router: オンデマンド ISR は安定しています |
v12.0.0 | Pages Router: ボット対応 ISR フォールバックが追加されました。 |
v9.5.0 | Pages Router: 安定版 ISR が導入されました。 |
役に立ちましたか?