データのフェッチ、キャッシュ、再検証
データ取得は、あらゆるアプリケーションの中核をなす部分です。このページでは、React と Next.js でデータをフェッチ、キャッシュ、再検証する方法について説明します。
データをフェッチする方法は 4 つあります:
fetch
を使用したサーバー上でのデータフェッチ- サードパーティライブラリを使用したサーバー上でのデータフェッチ
- ルートハンドラを介したクライアント上でのデータフェッチ
- サードパーティライブラリを使用したクライアント上でのデータフェッチ
fetch
を使用したサーバー上でのデータフェッチ
Next.js はネイティブのfetch
Web APIを拡張し、サーバー上の各 fetch リクエストに対するキャッシュと再検証の動作を設定できるようになりました。React はfetch
を拡張して、React コンポーネントツリーのレンダリ ング中にフェッチリクエストを自動的にメモします。
async/await
を使用した Server Components、Route ハンドラおよびServer Actionsでfetch
を使用できます。
例:
async function getData() {
const res = await fetch('https://api.example.com/...')
// 返り値はシリアライズされない
// Date, Map, Setを返すことができる
if (!res.ok) {
// 最も近い`error.js`エラーバウンダリが有効になる。
throw new Error('Failed to fetch data')
}
return res.json()
}
export default async function Page() {
const data = await getData()
return <main></main>
}
Good to know:
データのキャッシュ
キャッシュはデータを保存するので、リクエストのたびにデータソースから再フェッチする必要はありません。
デフォルトでは、Next.js はfetch
で返された値をサーバー上のデータ・キャッシュに自動的にキャッシュします。つまり、データはビルド時またはリクエスト時にfetch
され、キャッシュされて各データリクエストで再利用されます。
// 'force-cache'がデフォルトなので省略可能
fetch('https://...', { cache: 'force-cache' })
POST
メソッドを使用するfetch
リクエストも自動的にキャッシュされます。POST
メソッドを使うRoute ハンドラの内部でない限り、キャッシュされません。
データ・キャッシュとは何ですか?
データ・キャッシュは永続的なHTTP キャッシュです。プラットフォームによっては、キャッシュを自動的に拡張し、複数のリージョンで共有することができます。
データ・キャッシュの詳細については、こちらを参照してください。
データの再検証
再検証とは、データキャッシュを削除し、最新のデータを再取得するプロセスです。これは、データが変更され、最新の情報を確実に表示したい場合に使用します。
キャッシュされたデータは、2 つの方法で再検証できます:
- 時間ベースの再検証:一定時間が経過したデータを自動的に再検証します。これは、変更頻度が低く、鮮度がそれほど重要でないデータに有効です
- オンデマンドの再検証:イベント(フォーム送信など)に基づいてデータを手動で再検証します。オンデマンド再検証では、タグベースまたはパスベースのアプローチを使用して、データのグループを一度に再検証できます。これは、最新のデータをできるだけ早く表示したい場合に便利です(ヘッドレス CMS のコンテンツが更新された場合など)
時間ベースの再検証
時間間隔でデータを再検証するには、fetch
のnext.revalidate
オプションを使用して、リソースのキャッシュ有効期間(秒)を設定します。
fetch('https://...', { next: { revalidate: 3600 } })
あるいは、ルート Segment 内のすべてのfetch
リクエストを再検証するには、セグメント設定オプションを使用します。
export const revalidate = 3600 // 1時間ごとに再検証
静的にレンダリングされたルートに複数のfetch
リクエストがあり、それぞれに異なる再検証頻度が設定されている場合。もっとも低い時間がすべてのリクエストに使用されます。動的にレンダリングされるルートの場合、各fetch
リクエストは個別に再検証されます。
時間ベースの再検証の詳細については、こちらを参照してください。
オンデマンドの再検証
データは、Route Handler または Server Actions 内のパス(revalidatePath
)またはキャッシュタグ(revalidateTag
)によってオンデマンドで再検証できます。
Next.js には、ルート間のfetch
リクエストを無効にするためのキャッシュタグシステムがあります。
fetch
を使用する場合、キャッシュエントリに 1 つ以上のタグを付けるオプションがあります- その後、
revalidateTag
を呼び出して、そのタグに関連付けられたすべてのエントリを再検証できます
たとえば、次のfetch
リクエストはキャッシュ・タグ collection
を追加します:
export default async function Page() {
const res = await fetch('https://...', { next: { tags: ['collection'] } })
const data = await res.json()
// ...
}
その後、Server Action で revalidateTag
を呼び出すことで、collection
でタグ付けされたこのフェッチ・コールを再検証できます:
'use server'
import { revalidateTag } from 'next/cache'
export default async function action() {
revalidateTag('collection')
}
オンデマンドの再検証の詳細については、こちらを参照してください。
エラーハンドリングと再検証
データの再検証を試みてエラーがスローされた場合、最後に正常に生成されたデータがキャッシュから引き続き提供されます。次のリクエストで、Next.js はデータの再検証を再試行します。
データのキャッシュを停止する
fetch
リクエストは以下のケースではキャッシュされません:
cache: 'no-store
がfetch
リクエストに指定されているrevalidate: 0
オプションが個々のfetch
リクエストに指定されているfetch
リクエストがルートハンドラのPOST
メソッドで使用されているfetch
リクエストがheader
またはcookies
の後で使用されている- ルート Segment で
const dynamic = 'force-dynamic'
が指定されている - ルート Segment の
fetchCache
オプションがデフォルトでキャッシュをしないように指定されている fetch
リクエストでAuthorization
またはCookie
ヘッダーが指定されていて、コンポーネントツリー上にキャッシュされていないリクエストがある
個々のfetch
リクエスト
個々のfetch
リクエストに対してキャッシュを行わないようにするには、fetch
のキャッシュ・オプションを'no-store'
に設定します。これにより、リクエストごとに動的にデータがフェッチされます。
fetch('https://...', { cache: 'no-store' })
利用可能なすべてのcache
オプションは、 fetch API リファレンスを参照してください。
複数のfetch
リクエスト
ルート Segment(Layout や Page など)に複数のfetch
リクエストがある場合、Segment 設定オプションを使用して Segment 内のすべてのリクエストのキャッシュ動作を設定できます。
しかし、各取り込みリクエストのキャッシュ動作を個別に設定することをお勧めします。これにより、キャッシュ動作をより細 かく制御することができます。
サードパーティライブラリを使用したサーバー上でのデータフェッチ
fetch
をサポートまたは公開しないサードパーティライブラリ(データベース、CMS、ORM クライアントなど)を使用している場合は、ルート Segment の設定オプションと React のcache
関数を使用して、これらのリクエストのキャッシュと再検証の動作を設定できます。
データがキャッシュされるかどうかは、ルート Segment が静的にレンダリングされるか動的にレンダリングされるかに依存します。Segment が静的な場合(デフォルト)、リクエストの出力はキャッシュされ、ルート Segment の一部として再検証されます。Segment が動的な場合、リクエストの出力はキャッシュされず、Segment がレンダリングされる際、リクエストごとに再フェッチされます。
Experience 版のunstable_cache APIを使うこともできます。
例
下の例では
- React の
cache