コンテンツにスキップ

use cache

use cache ディレクティブを使用すると、ルート、React コンポーネント、または関数をキャッシュ可能としてマークできます。ファイルの一番上に使用すると、ファイル内のすべてのエクスポートがキャッシュされることを示します。また、関数やコンポーネントの一番上にインラインで使用すると、戻り値がキャッシュされます。

知っておくと良いこと: クッキーやヘッダーへのアクセスが必要なユーザー固有のコンテンツをキャッシュするには、「use cache: private」を参照してください。

使用方法

use cache は Cache Components 機能です。これを有効にするには、next.config.ts ファイルに cacheComponents オプションを追加してください。

next.config.ts
import type { NextConfig } from 'next'
 
const nextConfig: NextConfig = {
  cacheComponents: true,
}
 
export default nextConfig

次に、ファイル、コンポーネント、または関数のレベルで use cache を追加します。

// File level
'use cache'
 
export default async function Page() {
  // ...
}
 
// Component level
export async function MyComponent() {
  'use cache'
  return <></>
}
 
// Function level
export async function getData() {
  'use cache'
  const data = await fetch('/api/data')
  return data
}

use cache の仕組み

キャッシュキー

キャッシュエントリのキーは、その入力のシリアライズされたバージョンを使用して生成されます。これには以下が含まれます。

  • ビルド ID (ビルドごとに生成)
  • 関数 ID (関数固有のセキュアな識別子)
  • シリアライズ可能な関数引数 (またはプロップ)。

キャッシュされた関数に渡された引数、および親スコープから読み取られた値は、自動的にキーの一部になります。これは、入力が同じであれば、同じキャッシュエントリが再利用されることを意味します。

シリアライズ不可能な引数

シリアライズ不可能な引数、プロップ、またはクロージャで囲まれた値は、キャッシュされた関数内の参照に変換され、通過するだけで、検査または変更することはできません。これらのシリアライズ不可能な値はリクエスト時に埋め込まれ、キャッシュキーの一部にはなりません。

たとえば、キャッシュされた関数は JSX を children プロップとして受け取り、<div>{children}</div> を返すことができますが、実際の children オブジェクトを内部的に調べることはできません。これにより、キャッシュされていないコンテンツをキャッシュされたコンポーネント内にネストできます。

app/ui/cached-component.tsx
function CachedComponent({ children }: { children: ReactNode }) {
  'use cache'
  return <div>{children}</div>
}

戻り値

キャッシュ可能な関数の戻り値はシリアライズ可能である必要があります。これにより、キャッシュされたデータを正しく保存および取得できます。

ビルド時の use cache

layout または page の一番上に使用すると、ルートセグメントは事前レンダリングされ、後で 再検証できるようになります。

これは、use cache実行時データcookiesheaders など)と共に使用できないことを意味します。

注意: クッキー、ヘッダー、または検索パラメータに依存するコンテンツをキャッシュする必要がある場合は、代わりに「use cache: private」を使用してください。

実行時の use cache

サーバーでは、個々のコンポーネントまたは関数のキャッシュエントリはメモリ内にキャッシュされます。

次に、クライアントでは、サーバーキャッシュから返されたコンテンツは、セッション期間中、または 再検証されるまで、ブラウザのメモリに保存されます。

再検証中

デフォルトでは、use cache はサーバーサイドの再検証期間が15分です。この期間は頻繁な更新を必要としないコンテンツに役立つ場合がありますが、cacheLife および cacheTag API を使用して、個々のキャッシュエントリがいつ再検証されるかを構成できます。

  • cacheLife: キャッシュエントリの有効期間を構成します。
  • cacheTag: オンデマンド再検証用のタグを作成します。

これらの API は両方ともクライアントおよびサーバーのキャッシュレイヤー全体で統合されるため、1 つの場所でキャッシュセマンティクスを構成し、すべての場所に適用できます。

詳細については、cacheLife および cacheTag API ドキュメントを参照してください。

use cache によるルート全体のキャッシュ

ルート全体を事前レンダリングするには、layout ファイルと page ファイルの両方の一番上に use cache を追加します。これらの各セグメントは、アプリケーション内の個別のエントリーポイントとして扱われ、個別にキャッシュされます。

app/layout.tsx
'use cache'
 
export default function Layout({ children }: { children: ReactNode }) {
  return <div>{children}</div>
}

page ファイルにインポートされ、ネストされたコンポーネントは、page に関連付けられたキャッシュ出力の一部となります。

app/page.tsx
'use cache'
 
async function Users() {
  const users = await fetch('/api/users')
  // loop through users
}
 
export default function Page() {
  return (
    <main>
      <Users />
    </main>
  )
}

知っておくと良いこと:

  • use cachelayout または page のいずれかのみに追加された場合、そのルートセグメントとそれにインポートされたコンポーネントのみがキャッシュされます。
  • ルート内のネストされた子に 動的 API が使用されている場合、ルートは事前レンダリングからオプトアウトされます。

use cache によるコンポーネント出力のキャッシュ

コンポーネントレベルで use cache を使用すると、そのコンポーネント内で実行されるフェッチや計算をキャッシュできます。キャッシュエントリは、シリアライズされたプロップが各インスタンスで同じ値を生成する限り再利用されます。

app/components/bookings.tsx
export async function Bookings({ type = 'haircut' }: BookingsProps) {
  'use cache'
  async function getBookingsData() {
    const data = await fetch(`/api/bookings?type=${encodeURIComponent(type)}`)
    return data
  }
  return //...
}
 
interface BookingsProps {
  type: string
}

use cache による関数出力のキャッシュ

use cache は任意の非同期関数に追加できるため、コンポーネントやルートのみをキャッシュすることに限定されません。ネットワークリクエスト、データベースクエリ、または低速な計算をキャッシュしたい場合があります。

app/actions.ts
export async function getData() {
  'use cache'
 
  const data = await fetch('/api/data')
  return data
}

インターリービング

React では、children やスロットを使ったコンポジションは、柔軟なコンポーネントを構築するためのよく知られたパターンです。use cache を使用する場合でも、この方法で UI をコンポーズし続けることができます。返された JSX に children やその他のコンポジションスロットとして含まれるものは、キャッシュされたコンポーネントを通過しますが、そのキャッシュエントリには影響しません。

キャッシュ可能な関数の本体内で JSX スロットを直接参照しない限り、返された出力でのそれらの存在はキャッシュエントリに影響しません。

app/page.tsx
export default async function Page() {
  const uncachedData = await getData()
  return (
    // Pass compositional slots as props, e.g. header and children
    <CacheComponent header={<h1>Home</h1>}>
      {/* DynamicComponent is provided as the children slot */}
      <DynamicComponent data={uncachedData} />
    </CacheComponent>
  )
}
 
async function CacheComponent({
  header, // header: a compositional slot, injected as a prop
  children, // children: another slot for nested composition
}: {
  header: ReactNode
  children: ReactNode
}) {
  'use cache'
  const cachedData = await fetch('/api/cached-data')
  return (
    <div>
      {header}
      <PrerenderedComponent data={cachedData} />
      {children}
    </div>
  )
}

また、Server Actions をキャッシュされたコンポーネント経由で Client Component に渡すこともできます。これは、キャッシュ可能な関数内で呼び出すことなく行えます。

app/page.tsx
import ClientComponent from './ClientComponent'
 
export default async function Page() {
  const performUpdate = async () => {
    'use server'
    // Perform some server-side update
    await db.update(...)
  }
 
  return <CacheComponent performUpdate={performUpdate} />
}
 
async function CachedComponent({
  performUpdate,
}: {
  performUpdate: () => Promise<void>
}) {
  'use cache'
  // Do not call performUpdate here
  return <ClientComponent action={performUpdate} />
}
app/ClientComponent.tsx
'use client'
 
export default function ClientComponent({
  action,
}: {
  action: () => Promise<void>
}) {
  return <button onClick={action}>Update</button>
}

プラットフォームのサポート

デプロイメントオプションサポート
Node.jsサーバーはい
Dockerコンテナはい
静的エクスポートいいえ
アダプタープラットフォーム固有

Next.js をセルフホストする際の キャッシュ設定方法 を学びましょう。

バージョン履歴

バージョン変更履歴
v16.0.0"use cache" は Cache Components 機能で有効になります。
v15.0.0"use cache" は実験的な機能として導入されています。