本页还没有译文
本页 46 段还没译成日本語,下面显示的是英文原文。Caching and Revalidating (Previous Model)
还没翻译译自英文(nextjs.org)本页 46 段都还没译
This guide assumes you are not using Cache Components which was introduced in version 16 under the cacheComponents flag.
Caching fetch requests
By default, fetch requests are not cached. You can cache individual requests by setting the cache option to 'force-cache'.
export default async function Page() {
const data = await fetch('https://...', { cache: 'force-cache' })
}export default async function Page() {
const data = await fetch('https://...', { cache: 'force-cache' })
}See the fetch API reference to learn more.
unstable_cache for non-fetch functions
unstable_cache allows you to cache the result of database queries and other async functions that don't use fetch. Wrap unstable_cache around the function:
import { unstable_cache } from 'next/cache'
import { db } from '@/lib/db'
export const getCachedUser = unstable_cache(
async (id: string) => {
return db
.select()
.from(users)
.where(eq(users.id, id))
.then((res) => res[0])
},
['user'], // cache key prefix
{
tags: ['user'],
revalidate: 3600,
}
)import { unstable_cache } from 'next/cache'
import { db } from '@/lib/db'
export const getCachedUser = unstable_cache(
async (id) => {
return db
.select()
.from(users)
.where(eq(users.id, id))
.then((res) => res[0])
},
['user'], // cache key prefix
{
tags: ['user'],
revalidate: 3600,
}
)The third argument accepts:
tags: an array of tags for on-demand revalidation withrevalidateTag.revalidate: the number of seconds before the cache is revalidated.
See the unstable_cache API reference to learn more.
Route segment config
You can configure caching behavior at the route level by exporting config options from a Page, Layout, or Route Handler.
dynamic
Change the dynamic behavior of a layout or page to fully static or fully dynamic.
export const dynamic = 'auto'
// 'auto' | 'force-dynamic' | 'error' | 'force-static'export const dynamic = 'auto'
// 'auto' | 'force-dynamic' | 'error' | 'force-static''auto'(default): The default option to cache as much as possible without preventing any components from opting into dynamic behavior.'force-dynamic': Force dynamic rendering, which will result in routes being rendered for each user at request time. This option is equivalent to:- Setting the option of every
fetch()request in a layout or page to{ cache: 'no-store', next: { revalidate: 0 } }. - Setting the segment config to
export const fetchCache = 'force-no-store'
- Setting the option of every
'error': Force prerendering and cache the data of a layout or page by causing an error if any components use Request-time APIs or uncached data. This option is equivalent to:getStaticProps()in thepagesdirectory.- Setting the option of every
fetch()request in a layout or page to{ cache: 'force-cache' }. - Setting the segment config to
fetchCache = 'only-cache'.
'force-static': Force prerendering and cache the data of a layout or page by forcingcookies,headers()anduseSearchParams()to return empty values. It is possible torevalidate,revalidatePath, orrevalidateTag, in pages or layouts rendered withforce-static.
fetchCache
Time-based revalidation
Use the next.revalidate option on fetch to revalidate data after a specified number of seconds:
export default async function Page() {
const data = await fetch('https://...', { next: { revalidate: 3600 } })
}export default async function Page() {
const data = await fetch('https://...', { next: { revalidate: 3600 } })
}For non-fetch functions, unstable_cache accepts a revalidate option in its configuration (see example above).
Route segment config revalidate
Set the default revalidation time for a layout or page. This option does not override the revalidate value set by individual fetch requests.
export const revalidate = false
// false | 0 | numberexport const revalidate = false
// false | 0 | numberfalse(default): The default heuristic to cache anyfetchrequests that set theircacheoption to'force-cache'or are discovered before a Request-time API is used. Semantically equivalent torevalidate: Infinitywhich effectively means the resource should be cached indefinitely. It is still possible for individualfetchrequests to usecache: 'no-store'orrevalidate: 0to avoid being cached and make the route dynamically rendered. Or setrevalidateto a positive number lower than the route default to increase the revalidation frequency of a route.0: Ensure a layout or page is always dynamically rendered even if no Request-time APIs or uncached data fetches are discovered. This option changes the default offetchrequests that do not set acacheoption to'no-store'but leavesfetchrequests that opt into'force-cache'or use a positiverevalidateas is.number: (in seconds) Set the default revalidation frequency of a layout or page tonseconds.
Good to know
- The revalidate value needs to be statically analyzable. For example
revalidate = 600is valid, butrevalidate = 60 * 10is not. - The revalidate value is not available when using
runtime = 'edge'. - In Development, Pages are always rendered on-demand and are never cached. This allows you to see changes immediately without waiting for a revalidation period to pass.
Revalidation frequency
- The lowest
revalidateacross each layout and page of a single route will determine the revalidation frequency of the entire route. This ensures that child pages are revalidated as frequently as their parent layouts. - Individual
fetchrequests can set a lowerrevalidatethan the route's defaultrevalidateto increase the revalidation frequency of the entire route. This allows you to dynamically opt-in to more frequent revalidation for certain routes based on some criteria.
On-demand revalidation
To revalidate cached data after an event, use revalidateTag or revalidatePath in a Server Action or Route Handler.
Tagging cached data
Tag fetch requests with next.tags to enable on-demand cache invalidation:
export async function getUserById(id: string) {
const data = await fetch(`https://...`, {
next: { tags: ['user'] },
})
}export async function getUserById(id) {
const data = await fetch(`https://...`, {
next: { tags: ['user'] },
})
}For non-fetch functions, unstable_cache also accepts a tags option (see example above).
revalidateTag
Invalidate cached data by tag using revalidateTag:
import { revalidateTag } from 'next/cache'
export async function updateUser(id: string) {
// Mutate data
revalidateTag('user')
}import { revalidateTag } from 'next/cache'
export async function updateUser(id) {
// Mutate data
revalidateTag('user')
}revalidatePath
Invalidate all cached data for a specific route path using revalidatePath:
import { revalidatePath } from 'next/cache'
export async function updateUser(id: string) {
// Mutate data
revalidatePath('/profile')
}import { revalidatePath } from 'next/cache'
export async function updateUser(id) {
// Mutate data
revalidatePath('/profile')
}Deduplicating requests
If you are not using fetch (which is automatically memoized), and instead using an ORM or database directly, you can wrap your data access with the React cache function to deduplicate requests within a single render pass:
import { cache } from 'react'
import { db, posts, eq } from '@/lib/db'
export const getPost = cache(async (id: string) => {
const post = await db.query.posts.findFirst({
where: eq(posts.id, parseInt(id)),
})
})import { cache } from 'react'
import { db, posts, eq } from '@/lib/db'
export const getPost = cache(async (id) => {
const post = await db.query.posts.findFirst({
where: eq(posts.id, parseInt(id)),
})
})Preloading data
You can preload data by creating a utility function that you eagerly call above blocking requests. This lets you initiate data fetching early, so the data is already available by the time the component renders.
Combine the server-only package with React's cache to create a reusable preload utility:
import { cache } from 'react'
import 'server-only'
export const getItem = cache(async (id: string) => {
// ...
})
export const preload = (id: string) => {
void getItem(id)
}import { cache } from 'react'
import 'server-only'
export const getItem = cache(async (id) => {
// ...
})
export const preload = (id) => {
void getItem(id)
}Then call preload() before any blocking work so the data starts loading immediately:
import { getItem, preload, checkIsAvailable } from '@/lib/data'
export default async function Page({
params,
}: {
params: Promise<{ id: string }>
}) {
const { id } = await params
// Start loading item data
preload(id)
// Perform another asynchronous task
const isAvailable = await checkIsAvailable()
return isAvailable ? <Item id={id} /> : null
}
async function Item({ id }: { id: string }) {
const result = await getItem(id)
// ...
}import { getItem, preload, checkIsAvailable } from '@/lib/data'
export default async function Page({ params }) {
const { id } = await params
// Start loading item data
preload(id)
// Perform another asynchronous task
const isAvailable = await checkIsAvailable()
return isAvailable ? <Item id={id} /> : null
}
async function Item({ id }) {
const result = await getItem(id)
// ...
}