Next.jsのレンダリング方式:ISR(Incremental Static Regeneration)
Next.js v15.3.5時点でのApp RouterにおけるISRについての学習メモです。
ISRではほとんどのリクエストを静的なページとして表示することができるレンダリング方式である。また、SSGとは異なり、一定期間でページを更新することができるのである程度新しいコンテンツを維持することができる。 ISRは以下の方法で実現することができる。
Route Segment Configでrevalidateを設定する
Route Segment Configのrevalidateを設定する方法である。これは3種類の値を設定することができる。
false(default設定)
ページのキャッシュを無期限に設定し、Static Renderingとなる。
0
キャッシュを行わず、Dynamic Renderingとなる。
number
revalidateの間隔を秒数で設定できる。この秒数が経過した後にリクエストがあるとバックグラウンドでページが生成され、サーバーにキャッシュされる。ISRにするには秒数を設定する必要がある。
Route Segment Config #revalidate
export const revalidate = 3600 // 毎時間
export default async function Page() {
const data = await fetch('https://api.vercel.app/blog') // 1時間ごとにページを再生成する過程で再取得される
const posts: Post[] = await data.json()
return (
// ~~~~~~~~~~~~~~~~~~~~~
)
}fetch単位のrevalidateを設定する
fetch単位でもrevalidateを設定することができる。複数のfetchで異なるrevalidateを設定している時、ページの生成は最小のrevalidateの時間となるが、データフェッチはfetchに指定したrevalidateの時間でキャッシュされる。
export default async function Page() {
const data = await fetch('https://api.vercel.app/blog',{next: { revalidate: 60 }}) // 1分経過すると次のアクセスで再取得しキャッシュに保存する
const posts: Post[] = await data.json()
return (
// ~~~~~~~~~~~~~~~~~~~~~
)
}動的ルートでのISRを設定する
これはSSGの動的ルートに対して設定していたポイント+Route Segment Configのrevalidate設定で実現することができる。
mayuzu.me | Next.jsのレンダリング方式:SSG(Static Site Generation)
// /app/blogs/[id]
export const revalidate = 60; // 60秒に一回revalidateが走る
export const dynamicParams = true;
export async function generateStaticParams() {
const posts = await fetch('https://api.example.com/posts').then(res => res.json());
return posts.map((post: any) => ({
id: post.id.toString(), // ここで動的ページのIDパスに対応したプロパティでIDの一覧を返す
}));
}
export default async function PostPage({ params }: { params: { id: string } }) {
const post = await fetch(`https://api.example.com/posts/${params.id}`)
.then(res => res.json());
return (
<div>
<h1>{post.title}</h1>
<p>{post.content}</p>
</div>
);
}オンデマンドでのrevalidate
以下の二つの方式を使うことで、revalidateでのキャッシュを明示的に期限切れにすることができる。
revalidatePath
サーバーアクションでrevalidatePath()を使うことでそのパス配下のキャッシュを削除する。再度対象のパスにアクセスした際はデータソースに対して再度リクエストを行う
How to implement Incremental Static Regeneration (ISR)#revalidatePath
'use server'
import { revalidatePath } from 'next/cache'
export async function createPost() {
// Invalidate the /posts route in the cache
revalidatePath('/posts')
}revalidateTag
こちらはfetchごとに設定したtagに対してキャッシュを削除する。こちらも同様に再度対象のパスにアクセスした際はデータソースに対して再度リクエストを行う
How to implement Incremental Static Regeneration (ISR)#revalidatetag
export default async function Page() {
const data = await fetch('https://api.vercel.app/blog', {
next: { tags: ['posts'] }, // fetchにタグを設定する
})
const posts = await data.json()
// ...
}
~~~~~~~~~~~~~~~~~~~~~~~~
'use server'
import { revalidateTag } from 'next/cache'
export async function createPost() {
// Invalidate all data tagged with 'posts' in the cache
revalidateTag('posts') // サーバーアクションなどでタグを指定するとキャッシュを削除
}