Incremental Static Regeneration (ISR)
Next.js は、サイトの構築後に静的ページを作成または更新することができます。Incremental Static Regeneration(ISR)を利用すると、サイト全体を再構築する必要なく、ページごとに静的生成を行うことができます。ISR を使用すれば、何百万ものページにスケールアップしながら静的の恩恵を享受することができます。
Good to know: 現在、
edge
runtimeは ISR と互換性がありませんが、cache-control
header を手動で設定することにより、stale-while-revalidate
を利用することができます。
ISR を使うには、getStaticProps
にrevalidate
プロップを追加します:
function Blog({ posts }) {
return (
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
}
// This function gets called at build time on server-side.
// It may be called again, on a serverless function, if
// revalidation is enabled and a new request comes in
export async function getStaticProps() {
const res = await fetch("https://.../posts");
const posts = await res.json();
return {
props: {
posts,
},
// Next.js will attempt to re-generate the page:
// - When a request comes in
// - At most once every 10 seconds
revalidate: 10, // In seconds
};
}
// This function gets called at build time on server-side.
// It may be called again, on a serverless function, if
// the path has not been generated.
export async function getStaticPaths() {
const res = await fetch("https://.../posts");
const posts = await res.json();
// Get the paths we want to pre-render based on posts
const paths = posts.map((post) => ({
params: { id: post.id },
}));
// We'll pre-render only these paths at build time.
// { fallback: 'blocking' } will server-render pages
// on-demand if the path doesn't exist.
return { paths, fallback: "blocking" };
}
export default Blog;
request が、build 時に事前にレンダリングされたページに対して行われた場合、最初にキャッシュされたページが表示されます。
- 初回の request とその後の 10 秒以内にページに対する全てのリクエストもキャッシュされ、瞬時に処理されます。
- 10 秒の window の後でも、次の next request は依然としてキャッシュされた( stale )ページを表示します
- Next.js はバックグラウンドでページの再生成をトリガーします。
- ページが正常に生成されると、Next.js は cache を無効にし、更新されたページを表示します。バックグラウンドでの再生成が失敗した場合でも、古いページは変わらずそのままになります。
未生成の path に対して request があると、 Next.js は初回の request でページをサーバーレンダリングします。将来のリクエストは、 cache から静的ファイルを提供します。Vercel 上の ISR は、グローバルに cache を保持し、ロールバックを処理します 。
Good to know: あなたの上流データプロバイダが default で cache を有効化しているかどうか確認してください。 cache を無効化しなければならない場合があります(例:
useCdn: false
)。そうでないと、再検証が新しいデータを引っ張ってくることができず、 ISR cache を更新することができません。 キャッシングは、request されたエンドポイントで CDN(Cache-Control
header が戻るとき)で発生する可能性があります。
On-Demand Revalidation
revalidate
の時間を60
に設定すると、すべての訪問者は 1 分間、同じ生成された version のサイトを見ることになります。cache を無効にする唯一の方法は、1 分が経過した後にそのページを訪れる人からです。
v12.2.0
から始まり、Next.js cache は、特定のページの Next.js キャッシュを手動でパージするためのオンデマンドの Incremental Static Regeneration をサポートします。これにより、以下の場合にサイトの更新が容易になります:
- ヘッドレス CMS からのコンテントが作成または更新されました
- E コマースの metadata の変更(価格、 description 、カテゴリー、レビューなど)
getStaticProps
の中では、オンデマンド再検証を使用するためにrevalidate
を指定する必要はありません。もしrevalidate
が省略された場合、Next.js はfalse
(再検証なし)の defaultvalue を使用し、revalidate()
が呼び出されたときにのみ、ページを再検証します。
Good to know: Middlewareは、オンデマンドの ISR リクエストで実行されません。代わりに、再確認したい path に対して
revalidate()
を呼び出します。例えば、pages/blog/[slug].js
があり、/post-1
から/blog/post-1
への rewrite がある場合、res.revalidate('/blog/post-1')
を呼び出す必要があります。
オンデマンド再検証の使用
まず、Next.js app だけが知っている secret トークンを作成します。この secret は、API Route への不正なアクセスを防ぐために使用されます。次の URL 構造を使用して route(手動または webhook で)にアクセスできます。
https://<your-site.com>/api/revalidate?secret=<token>
次に、secret をアプリケーションのEnvironment Variableとして追加します。最後に、リバリデーションの API Route を作成します:
export default async function handler(req, res) {
// Check for secret to confirm this is a valid request
if (req.query.secret !== process.env.MY_SECRET_TOKEN) {
return res.status(401).json({ message: 'Invalid token' })
}
try {
// this should be the actual path not a rewritten path
// e.g. for "/blog/[slug]" this should be "/blog/post-1"
await res.revalidate('/path-to-revalidate')
return res.json({ revalidated: true })
} catch (err) {
// If there was an error, Next.js will continue
// to show the last successfully generated page
return res.status(500).send('Error revalidating')
}
}
弊社のデモをご覧ください 。オンデマンド再検証がどのように動作するかを確認し、フィードバックを提供してください。
development 中のオンデマンド ISR のテスト
next dev
でローシーで動作する場合、getStaticProps
はすべての request で呼び出されます。ISR の設定が正しいかを確認するには、 production build を作成し、 production server: を start する必要があります。
next build
next start
その後、静的ページが正常に再検証されたことを確認できます。
Error handling and revalidation
getStaticProps
でバックグラウンド再生を処理中に error が発生した場合、または手動で error をスローした場合でも、最後に正常に生成されたページが表示され続けます。次の next の request では、 Next.js がgetStaticProps
を再試行します。
export async function getStaticProps() {
// If this request throws an uncaught error, Next.js will
// not invalidate the currently shown page and
// retry getStaticProps on the next request.
const res = await fetch("https://.../posts");
const posts = await res.json();
if (!res.ok) {
// If there is a server error, you might want to
// throw an error instead of returning so that the cache is not updated
// until the next successful request.
throw new Error(`Failed to fetch posts, received status ${res.status}`);
}
// If the request was successful, return the posts
// and revalidate every 10 seconds.
return {
props: {
posts,
},
revalidate: 10,
};
}
Self-hosting ISR
Incremental Static Regeneration (ISR)は、next start
を使用すると、自己ホスト型の Next.js サイトで手間なく動作します。
self-hosting Next.jsについてさらに学ぶ。
Version History
Version | Changes |
---|---|
v14.1.0 | カスタム cacheHandler は安定しています。 |
v12.2.0 | オンデマンド ISR は安定しています |
v12.1.0 | オンデマンド ISR 追加(ベータ版)。 |
v12.0.0 | ボットに対応した ISR fallback が追加されました。 |
v9.5.0 | ベース Path が追加されました。 |