Menu

use cache

Die use cache-Direktive kennzeichnet eine Komponente, Funktion oder Datei zur Zwischenspeicherung. Sie kann am Anfang einer Datei verwendet werden, um anzuzeigen, dass alle Funktionen in der Datei zwischenspeicherbar sind, oder inline am Anfang einer Funktion, um diese als zwischenspeicherbar zu markieren. Dies ist eine experimentelle Next.js-Funktion und keine native React-Funktion wie use client oder use server.

Aktivieren Sie die Unterstützung für die use cache-Direktive mit dem dynamicIO-Flag in Ihrer next.config.ts-Datei:

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

Die use cache-Direktive wird in Zukunft separat vom dynamicIO-Flag verfügbar sein.

Zwischenspeicherung ist eine Technik zur Leistungsverbesserung von Webanwendungen durch Speicherung der Ergebnisse von Rendering- oder Datenanfragen. Wenn Sie eine asynchrone Funktion oder APIs verwenden, die von Anfragezeitdaten abhängen, wird Next.js automatisch dynamisches Rendering aktivieren. Sie können die Ergebnisse dieser Operationen explizit zwischenspeichern und die Rendering-Leistung Ihrer Anwendung mit der use cache-Direktive optimieren.

Die use cache-Direktive ist eine experimentelle Funktion, die darauf abzielt, die unstable_cache-Funktion zu ersetzen. Im Gegensatz zu unstable_cache, das auf die Zwischenspeicherung von JSON-Daten beschränkt ist und manuelle Definition von Revalidierungszeiträumen und -tags erfordert, bietet use cache mehr Flexibilität. Es ermöglicht die Zwischenspeicherung einer breiteren Palette von Daten, einschließlich allem, was React Server Components (RSC) serialisieren können, sowie Datenabfrage-Ausgaben und Komponentenausgaben.

Zusätzlich verwaltet use cache Komplexitäten automatisch, indem Eingaben und Ausgaben verfolgt werden, wodurch die Wahrscheinlichkeit von versehentlicher Cachevergiftung verringert wird. Da es Eingaben und Ausgaben serialisiert, können Probleme mit falscher Cacheabfrage vermieden werden.

use cache-Direktive

Die Next.js use cache-Direktive ermöglicht die Zwischenspeicherung ganzer Routen, Komponenten und Funktionsrückgabewerte. Wenn Sie eine asynchrone Funktion haben, können Sie diese als zwischenspeicherbar markieren, indem Sie use cache am Anfang der Datei oder innerhalb des Funktionsbereichs hinzufügen. Dies informiert Next.js, dass der Rückgabewert zwischengespeichert und für nachfolgende Renderings wiederverwendet werden kann.

// Dateiebene
'use cache'
 
export default async function Page() {
  // ...
}
 
// Komponentenebene
export async function MyComponent() {
  'use cache'
  return <></>
}
 
// Funktionsebene
export async function getData() {
  'use cache'
  const data = await fetch('/api/data')
  return data
}

Hinweis: Funktionen, die die use cache-Direktive verwenden, dürfen keine Nebenwirkungen haben, wie z.B. Zustandsänderungen, direktes DOM-Manipulation oder Setzen von Zeitgebern zur Intervallausführung

Revalidierung

Standardmäßig setzt Next.js einen Revalidierungszeitraum von 15 Minuten, wenn Sie die use cache-Direktive verwenden. Next.js setzt eine Ablaufdauer, die fast unendlich ist, was bedeutet, dass sie für Inhalte geeignet ist, die nicht häufig aktualisiert werden müssen.

Während dieser Revalidierungszeitraum nützlich für Inhalte sein kann, die sich nicht oft ändern, können Sie die APIs cacheLife und cacheTag verwenden, um das Cacheverhalten zu konfigurieren:

  • cacheLife: Für zeitbasierte Revalidierungszeiträume.
  • cacheTag: Für On-Demand-Revalidierung.

Beide APIs integrieren sich über Client- und Server-Caching-Schichten hinweg, sodass Sie Ihre Caching-Semantik an einer Stelle konfigurieren und überall anwenden können.

Grundlegendes Beispiel:

Das folgende Beispiel zeigt, wie Sie die cacheLife-Funktion auf Funktionsebene verwenden, um einen Revalidierungszeitraum von einem Tag für die Funktionsausgabe festzulegen:

app/components/my-component.tsx
import { unstable_cacheLife as cacheLife } from 'next/cache'
 
export async function MyComponent() {
  async function getData() {
    'use cache'
    cacheLife('days')
    const data = await fetch('/api/data')
    return data
  }
 
  return // Daten hier verwenden
}

Wie Cache-Revalidierung funktioniert

Wenn ein Revalidierungszeitraum von fünfzehn Minuten festgelegt wird, geschieht Folgendes:

  1. Cache-TREFFER: Wenn innerhalb des 15-Minuten-Fensters eine Anfrage gestellt wird, werden die zwischengespeicherten Daten bereitgestellt und sind ein Cache-TREFFER.
  2. Veraltete Daten: Wenn die Anfrage nach 15 Minuten erfolgt, wird der zwischengespeicherte Wert weiterhin bereitgestellt, ist aber jetzt als veraltet anzusehen. Next.js wird im Hintergrund einen neuen Cache-Eintrag neu berechnen.
  3. Cache-MISS: Wenn der Cache-Eintrag abläuft und eine nachfolgende Anfrage gestellt wird, behandelt Next.js dies als Cache-MISS, und die Daten werden neu berechnet und erneut von der Quelle abgerufen.

Zeitbasierte Revalidierung mit cacheLife

Die cacheLife-Funktion kann nur dort verwendet werden, wo die use cache-Direktive vorhanden ist, und ermöglicht die Definition zeitbasierter Revalidierungszeiträume basierend auf Cache-Profilen.

Wir empfehlen, bei Verwendung der use cache-Direktive immer ein Cache-Profil hinzuzufügen, um das Cacheverhalten explizit zu definieren.

Cache-Profile sind Objekte mit folgenden Eigenschaften:

EigenschaftWertBeschreibungAnforderung
stalenumberDauer, die der Client einen Wert zwischenspeichern soll, ohne den Server zu überprüfen.Optional
revalidatenumberHäufigkeit, mit der der Cache auf dem Server aktualisiert werden soll; veraltete Werte können während der Revalidierung bereitgestellt werden.Optional
expirenumberMaximale Dauer, für die ein Wert veraltet bleiben kann, bevor auf dynamisches Abrufen umgeschaltet wird; muss länger sein als revalidate.Optional - Muss länger sein als revalidate

Die Eigenschaft "stale" unterscheidet sich von der Einstellung staleTimes dahingehend, dass sie speziell die Client-seitige Router-Zwischenspeicherung steuert. Während staleTimes eine globale Einstellung ist, die alle Instanzen sowohl dynamischer als auch statischer Daten beeinflusst, ermöglicht die cacheLife-Konfiguration die Definition von "stale"-Zeiten auf Funktions- oder Routenebene.

Hinweis: Die Eigenschaft "stale" setzt nicht den Header Cache-control: max-age. Stattdessen steuert sie den Client-seitigen Router-Cache.

Standard-Cache-Profile

Next.js bietet eine Reihe benannter Cache-Profile, die auf verschiedenen Zeitskalen modelliert sind. Wenn Sie kein Cache-Profil in der cacheLife-Funktion neben der use cache-Direktive angeben, wendet Next.js automatisch das "default" Cache-Profil an.

ProfilStaleRevalidateExpireBeschreibung
defaultundefined15 MinutenUNENDLICHER_CACHEStandard-Profil, geeignet für Inhalte, die keine häufigen Updates benötigen
secondsundefined1 Sekunde1 MinuteFür sich schnell ändernde Inhalte, die nahezu Echtzeit-Updates erfordern
minutes5 Minuten1 Minute1 StundeFür Inhalte, die sich innerhalb einer Stunde häufig aktualisieren
hours5 Minuten1 Stunde1 TagFür Inhalte, die täglich aktualisiert werden, aber leicht veraltet sein können
days5 Minuten1 Tag1 WocheFür Inhalte, die wöchentlich aktualisiert werden, aber einen Tag alt sein können
weeks5 Minuten1 Woche1 MonatFür Inhalte, die monatlich aktualisiert werden, aber eine Woche alt sein können
max5 Minuten1 MonatUNENDLICHER_CACHEFür sehr stabile Inhalte, die nur selten aktualisiert werden müssen

Grundbeispiel:

app/page.tsx
'use cache'
import { unstable_cacheLife as cacheLife } from 'next/cache'
 
cacheLife('minutes')

Die verwendeten Zeichenfolgewerte zur Referenzierung von Cache-Profilen tragen keine inhärente Bedeutung; stattdessen dienen sie als semantische Bezeichner. Dies ermöglicht Ihnen, Ihre zwischengespeicherten Inhalte in Ihrer Codebasis besser zu verstehen und zu verwalten.

Definieren wiederverwendbarer Cache-Profile

Sie können ein wiederverwendbares Cache-Profil erstellen, indem Sie es in Ihrer next.config.ts-Datei definieren. Wählen Sie einen Namen, der Ihrem Anwendungsfall entspricht, und legen Sie Werte für die Eigenschaften stale, revalidate und expire fest. Sie können so viele benutzerdefinierte Cache-Profile erstellen, wie benötigt. Jedes Profil kann über seinen Namen als Zeichenfolgewert an die cacheLife-Funktion übergeben werden.

next.config.ts
const nextConfig = {
  experimental: {
    dynamicIO: true,
    cacheLife: {
      biweekly: {
        stale: 60 * 60 * 24 * 14, // 14 Tage
        revalidate: 60 * 60 * 24, // 1 Tag
        expire: 60 * 60 * 24 * 14, // 14 Tage
      },
    },
  },
}
 
module.exports = nextConfig

Das obige Beispiel speichert 14 Tage zwischen, prüft täglich auf Updates und lässt den Cache nach 14 Tagen ablaufen. Sie können dann dieses Profil in Ihrer gesamten Anwendung über seinen Namen referenzieren:

app/page.tsx
'use cache'
import { unstable_cacheLife as cacheLife } from 'next/cache'
 
cacheLife('biweekly')
 
// restlicher Code

Überschreiben der Standard-Cache-Profile

Während die Standard-Cache-Profile eine nützliche Möglichkeit bieten, darüber nachzudenken, wie frisch oder veraltet eine bestimmte Ausgabe sein kann, bevorzugen Sie möglicherweise unterschiedlich benannte Profile, um Ihre Caching-Strategien besser abzubilden.

Sie können die Standard-Cache-Profile überschreiben, indem Sie eine neue Konfiguration mit demselben Namen wie die Standardeinstellungen erstellen.

Das folgende Beispiel zeigt, wie das Standard-Cache-Profil "days" überschrieben wird:

next.config.ts
const nextConfig = {
  experimental: {
    dynamicIO: true,
    cacheLife: {
      days: {
        stale: 3600, // 1 Stunde
        revalidate: 900, // 15 Minuten
        expire: 86400, // 1 Tag
      },
    },
  },
}
 
module.exports = nextConfig

Definieren von Cache-Profilen inline

Für spezifische Anwendungsfälle können Sie ein benutzerdefiniertes Cache-Profil festlegen, indem Sie ein Objekt an die cacheLife-Funktion übergeben:

app/page.tsx
'use cache'
import { unstable_cacheLife as cacheLife } from 'next/cache'
 
cacheLife({
  stale: 3600, // 1 Stunde
  revalidate: 900, // 15 Minuten
  expire: 86400, // 1 Tag
})
 
// restlicher Code

Dieses Inline-Cache-Profil wird nur auf die Funktion oder Datei angewendet, in der es erstellt wurde. Wenn Sie dasselbe Profil in Ihrer gesamten Anwendung wiederverwenden möchten, können Sie die Konfiguration zur cacheLife-Eigenschaft Ihrer next.config.ts-Datei hinzufügen.

Verschachtelte Verwendung von use cache und cacheLife

Bei der Definition mehrerer Caching-Verhaltensweisen in derselben Route oder Komponentenstruktur wird der äußere Cache, wenn die inneren Caches ihr eigenes cacheLife-Profil angeben, die kürzeste Cache-Dauer unter ihnen berücksichtigen. Dies gilt nur, wenn der äußere Cache kein eigenes explizites cacheLife-Profil definiert hat.

Entscheidungshierarchie für Cache-Grenzen:

  1. Next.js verwendet das kürzeste Cache-Profil, das innerhalb der gesamten use cache-Grenze gefunden wird, ohne die inneren use cache-Direktiven.
  2. Wenn kein Cache-Profil existiert, gilt das kürzeste Profilzeitintervall von allen inneren use cache-Aufrufen für dieses use cache. Wenn es keine inneren use cache-Aufrufe gibt, wird der Standardwert verwendet.
  3. Innere Caches in zwei Ebenen tiefer beeinflussen den äußeren Cache nicht, da sie ihre Dauer bereits an ihr übergeordnetes Element übergeben haben.

Zum Beispiel wird, wenn Sie die use cache-Direktive auf Ihrer Seite hinzufügen, ohne ein Cache-Profil anzugeben, implizit das Standard-Cache-Profil angewendet (cacheLife("default")). Wenn eine in die Seite importierte Komponente die use cache-Direktive mit ihrem eigenen Cache-Profil verwendet, werden das äußere und innere Cache-Profil verglichen, und die kürzeste in den Profilen festgelegte Dauer wird angewendet.

app/components/parent.tsx
// Elternkomponente
import { unstable_cacheLife as cacheLife } from 'next/cache'
import { ChildComponent } from './child'
 
export async function ParentComponent() {
  'use cache'
  cacheLife('days')
 
  return (
    <div>
      <ChildComponent />
    </div>
  )
}

Und in einer separaten Datei definieren wir die Kindkomponente, die importiert wurde:

app/components/child.tsx
// Kindkomponente
import { unstable_cacheLife as cacheLife } from 'next/cache'
 
export async function ChildComponent() {
  'use cache'
  cacheLife('hours')
  return <div>Kindinhalt</div>
 
  // Der Cache dieser Komponente respektiert das kürzere 'hours'-Profil
}

Bedarfsgerechte Neuladen mit cacheTag

Ein cacheTag wird in Kombination mit revalidateTag verwendet, um Cachedaten bei Bedarf zu bereinigen. Die cacheTag-Funktion akzeptiert einen einzelnen Zeichenfolgewert oder ein Zeichenfolgenarray.

Im folgenden Beispiel verwendet die getData-Funktion das "weeks" Cache-Profil und definiert einen cacheTag für die zwischengespeicherte Ausgabe:

app/actions.ts
import {
  unstable_cacheTag as cacheTag,
  unstable_cacheLife as cacheLife,
} from 'next/cache'
 
export async function getData() {
  'use cache'
  cacheLife('weeks')
  cacheTag('my-data')
 
  const data = await fetch('/api/data')
  return data
}

Sie können den Cache dann bei Bedarf mit der revalidateTag-API in einer anderen Funktion bereinigen, zum Beispiel in einem Routenhandler oder einer Serveraktion:

app/submit.ts
'use server'
 
import { revalidateTag } from 'next/cache'
 
export default async function submit() {
  await addPost()
  revalidateTag('my-data')
}

Weitere Informationen zum Bereinigen von Cachedaten bei Bedarf finden Sie in der revalidateTag-Dokumentation.

Beispiele

Zwischenspeichern ganzer Routen mit use cache

Die Platzierung von Suspense-Grenzen in Ihrer Anwendung bestimmt, wie dynamisch Ihre Komponenten sein können. Komponenten innerhalb einer Suspense-Grenze dürfen dynamisch sein, aber das bedeutet nicht, dass sie automatisch dynamisch sind. Wenn Sie alles zwischenspeichern oder Ihr Inhalt statisch ist, wird Next.js weiterhin eine statische Anwendung generieren. Die Verwendung von Suspense zeigt an, dass dynamisches Verhalten innerhalb der Grenze erlaubt ist.

Um sicherzustellen, dass Ihre Route statisch bleibt, vermeiden Sie die Verwendung von Suspense-Grenzen. Wenn Sie sie verwenden müssen, können Sie eine statische Seite aufrechterhalten, indem Sie die use cache-Direktive sowohl für Layout- als auch für Seitenkomponenten hinzufügen, da sie als separate Einstiegspunkte in Ihrer Anwendung behandelt werden.

Dies wird für Anwendungen empfohlen, die zuvor die Option export const dynamic = "force-cache" verwendet haben, und wird sicherstellen, dass die gesamte Route vorgerendert wird.

app/layout.tsx
"use cache"
import { unstable_cacheLife as cacheLife } from 'next/cache'
cacheLife('minutes')
 
export default Layout({children}: {children: ReactNode}) {
  return <div>{children}</div>
}

Und in Ihrer page.tsx-Datei können Sie die use cache-Direktive oben in der Datei hinzufügen und ein Cache-Profil definieren:

app/page.tsx
"use cache"
import { unstable_cacheLife as cacheLife } from 'next/cache'
cacheLife('minutes')
 
async function Users() {
  const users = await fetch('/api/users');
  // Schleife durch Benutzer
}
 
export default Page() {
  return (
    <main>
      <Users/>
    </main>
  )
}

Zwischenspeichern der Komponentenausgabe mit use cache

Sie können use cache auf Komponentenebene verwenden, um beliebige Abrufe oder Berechnungen innerhalb dieser Komponente zu speichern. Wenn Sie die Komponente in Ihrer gesamten Anwendung wiederverwenden, kann sie denselben Cache-Eintrag teilen, solange die Props dieselbe Struktur beibehalten.

Die Props werden serialisiert und bilden einen Teil des Cache-Schlüssels. Wenn Sie die gleiche Komponente an verschiedenen Stellen in Ihrer Anwendung verwenden, wird der Cache-Eintrag wiederverwendet, solange die serialisierten Props in jeder Instanz den gleichen Wert erzeugen.

app/components/bookings.tsx
import { unstable_cacheLife as cacheLife } from 'next/cache'
 
interface BookingsProps {
  type: string
}
 
export async function Bookings({ type = 'massage' }: BookingsProps) {
  'use cache'
  cacheLife('minutes')
 
  async function getBookingsData() {
    const data = await fetch(`/api/bookings?type=${encodeURIComponent(type)}`)
    return data
  }
  return //...
}

Zwischenspeichern von Funktionsergebnissen mit use cache

Da Sie use cache zu jeder asynchronen Funktion hinzufügen können, sind Sie nicht darauf beschränkt, nur Komponenten oder Routen zu cachen. Sie möchten vielleicht eine Netzwerkanfrage oder Datenbankabfrage zwischenspeichern oder etwas berechnen, das sehr langsam ist. Wenn Sie use cache zu einer Funktion hinzufügen, die diese Art von Arbeit enthält, wird sie cachebar, und bei der Wiederverwendung teilt sie den gleichen Cache-Eintrag.

app/actions.ts
import { unstable_cacheLife as cacheLife } from 'next/cache'
 
export async function getData() {
  'use cache'
  cacheLife('minutes')
 
  const data = await fetch('/api/data')
  return data
}