コンテンツにスキップ
App RouterGetting StartedCaching and Revalidating

キャッシュと再検証

キャッシュは、データ取得やその他の計算結果を保存し、同じデータに対する将来のリクエストを、再度作業を行うことなく、より高速に処理できるようにする技術です。一方、再検証により、アプリケーション全体を再構築することなくキャッシュエントリを更新できます。

Next.js は、キャッシュと再検証を処理するためのいくつかの API を提供します。このガイドでは、それらをいつ、どのように使用するかを説明します。

fetch

デフォルトでは、fetch リクエストはキャッシュされません。cache オプションを 'force-cache' に設定することで、個々のリクエストをキャッシュできます。

app/page.tsx
export default async function Page() {
  const data = await fetch('https://...', { cache: 'force-cache' })
}

知っておくと良いこと: デフォルトでは fetch リクエストはキャッシュされませんが、Next.js は fetch リクエストを含むルートを プリレンダリングし、HTML をキャッシュします。ルートを 動的にすることを保証したい場合は、connection API を使用してください。

fetch リクエストによって返されたデータを再検証するには、next.revalidate オプションを使用できます。

app/page.tsx
export default async function Page() {
  const data = await fetch('https://...', { next: { revalidate: 3600 } })
}

これにより、指定された秒数後にデータが再検証されます。

詳細については、fetch API リファレンス を参照してください。

unstable_cache

unstable_cache は、データベースクエリやその他の非同期関数の結果をキャッシュできるようにします。使用するには、関数の周りを unstable_cache でラップします。例:

app/lib/data.ts
import { db } from '@/lib/db'
export async function getUserById(id: string) {
  return db
    .select()
    .from(users)
    .where(eq(users.id, id))
    .then((res) => res[0])
}
app/page.tsx
import { unstable_cache } from 'next/cache'
import { getUserById } from '@/app/lib/data'
 
export default async function Page({
  params,
}: {
  params: Promise<{ userId: string }>
}) {
  const { userId } = await params
 
  const getCachedUser = unstable_cache(
    async () => {
      return getUserById(userId)
    },
    [userId] // add the user ID to the cache key
  )
}

この関数は、キャッシュがどのように再検証されるかを定義するために、3 番目のオプションオブジェクトを受け取ります。これには以下が含まれます:

  • tags:Next.js がキャッシュを再検証するために使用するタグの配列。
  • revalidate:キャッシュが再検証されるまでの秒数。
app/page.tsx
const getCachedUser = unstable_cache(
  async () => {
    return getUserById(userId)
  },
  [userId],
  {
    tags: ['user'],
    revalidate: 3600,
  }
)

詳細については、unstable_cache API リファレンス を参照してください。

revalidateTag

revalidateTag は、イベントの後にタグに基づいてキャッシュエントリを再検証するために使用されます。この関数は現在 2 つの動作をサポートしています。

  • profile="max" 付き:stale-while-revalidate セマンティクスを使用し、バックグラウンドで最新のコンテンツを取得しながら古いコンテンツを提供します。
  • 2 番目の引数なし:キャッシュを即座に期限切れにするレガシー動作(非推奨)。

fetch で使用するには、まず next.tags オプションで関数にタグを付けます。

app/lib/data.ts
export async function getUserById(id: string) {
  const data = await fetch(`https://...`, {
    next: {
      tags: ['user'],
    },
  })
}

または、tags オプションで unstable_cache 関数にマークを付けることもできます。

app/lib/data.ts
export const getUserById = unstable_cache(
  async (id: string) => {
    return db.query.users.findFirst({ where: eq(users.id, id) })
  },
  ['user'], // Needed if variables are not passed as parameters
  {
    tags: ['user'],
  }
)

次に、Route Handler または Server Action で revalidateTag を呼び出します。

app/lib/actions.ts
import { revalidateTag } from 'next/cache'
 
export async function updateUser(id: string) {
  // Mutate data
  revalidateTag('user', 'max') // Recommended: Uses stale-while-revalidate
}

複数の関数で同じタグを再利用して、すべてを一度に再検証できます。

詳細については、revalidateTag API リファレンス を参照してください。

revalidatePath

revalidatePath は、イベントの後にルートを再検証するために使用されます。使用するには、Route Handler または Server Action で呼び出します。

app/lib/actions.ts
import { revalidatePath } from 'next/cache'
 
export async function updateUser(id: string) {
  // Mutate data
  revalidatePath('/profile')

詳細については、revalidatePath API リファレンス を参照してください。

updateTag

updateTag は、Server Action で読み取り専用の書き込みシナリオのためにキャッシュされたデータを即座に期限切れにするために特別に設計されています。revalidateTag とは異なり、Server Action 内でのみ使用でき、キャッシュエントリを即座に期限切れにします。

app/lib/actions.ts
import { updateTag } from 'next/cache'
import { redirect } from 'next/navigation'
 
export async function createPost(formData: FormData) {
  // Create post in database
  const post = await db.post.create({
    data: {
      title: formData.get('title'),
      content: formData.get('content'),
    },
  })
 
  // Immediately expire cache so the new post is visible
  updateTag('posts')
  updateTag(`post-${post.id}`)
 
  redirect(`/posts/${post.id}`)
}

revalidateTagupdateTag の主な違い

  • updateTag:Server Action のみ、キャッシュを即座に期限切れにし、読み取り専用の書き込みに使用します。
  • revalidateTag:Server Action および Route Handler で使用され、profile="max" で stale-while-revalidate をサポートします。

詳細については、updateTag API リファレンス を参照してください。