-
Notifications
You must be signed in to change notification settings - Fork 28.5k
Docs IA 2.0: Add Caching and Revalidating
page
#79493
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+291
−253
Merged
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
1753cae
Reorder
delbaoliveira c43c499
Reorder
delbaoliveira bd336c4
Remove duplicate warning
delbaoliveira 926a166
Delete old content
delbaoliveira d3e585f
Add deduplication section
delbaoliveira f76fb57
Intro
delbaoliveira c0edfa3
With `fetch`
delbaoliveira b5255a6
With unstable_cache
delbaoliveira 2b493df
Cleaner headings
delbaoliveira 9387294
revalidateTag
delbaoliveira 887183f
revalidatePath
delbaoliveira ad4dd62
Add cta
delbaoliveira 406379e
broken links
delbaoliveira 5a77ba4
Broken link
delbaoliveira 1e667ed
Broken redirect
delbaoliveira 48dc311
Merge branch 'canary' into docs-caching-revalidating-gs
delbaoliveira fa88b95
Add missing JS code block
delbaoliveira File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
250 changes: 250 additions & 0 deletions
250
docs/01-app/01-getting-started/09-caching-and-revalidating.mdx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,250 @@ | ||
--- | ||
title: How to cache and revalidate data | ||
nav_title: Caching and Revalidating | ||
description: Learn how to cache and revalidate data in your application. | ||
related: | ||
title: API Reference | ||
description: Learn more about the features mentioned in this page by reading the API Reference. | ||
links: | ||
- app/api-reference/functions/fetch | ||
- app/api-reference/functions/unstable_cache | ||
- app/api-reference/functions/revalidatePath | ||
- app/api-reference/functions/revalidateTag | ||
--- | ||
|
||
Caching is a technique for storing the result of data fetching and other computations so that future requests for the same data can be served faster, without doing the work again. While revalidation allows you to update cache entries without having to rebuild your entire application. | ||
|
||
Next.js provides a few APIs to handle caching and revalidation. This guide will walk you through when and how to use them. | ||
|
||
- [`fetch`](#fetch) | ||
- [`unstable_cache`](#unstable_cache) | ||
- [`revalidatePath`](#revalidatepath) | ||
- [`revalidateTag`](#revalidatetag) | ||
|
||
### `fetch` | ||
|
||
By default, [`fetch`](/docs/app/api-reference/functions/fetch) requests are not cached. You can cache individual requests by setting the `cache` option to `'force-cache'`. | ||
|
||
```tsx filename="app/page.tsx" switcher | ||
export default async function Page() { | ||
const data = await fetch('https://...', { cache: 'force-cache' }) | ||
} | ||
``` | ||
|
||
```jsx filename="app/page.jsx" switcher | ||
export default async function Page() { | ||
const data = await fetch('https://...', { cache: 'force-cache' }) | ||
} | ||
``` | ||
|
||
> **Good to know**: Although `fetch` requests are not cached by default, Next.js will [prerender](/docs/app/getting-started/partial-prerendering#static-rendering) routes that have `fetch` requests and cache the HTML. If you want to guarantee a route is [dynamic](/docs/app/getting-started/partial-prerendering#dynamic-rendering), use the [`connection` API](/docs/app/api-reference/functions/connection). | ||
|
||
To revalidate the data returned by a `fetch` request, you can use the `next.revalidate` option. | ||
|
||
```tsx filename="app/page.tsx" switcher | ||
export default async function Page() { | ||
const data = await fetch('https://...', { next: { revalidate: 3600 } }) | ||
} | ||
``` | ||
|
||
```jsx filename="app/page.jsx" switcher | ||
export default async function Page() { | ||
const data = await fetch('https://...', { next: { revalidate: 3600 } }) | ||
} | ||
``` | ||
|
||
This will revalidate the data after a specified amount of seconds. | ||
|
||
See the [`fetch` API reference](/docs/app/api-reference/functions/fetch) to learn more. | ||
|
||
### `unstable_cache` | ||
|
||
`unstable_cache` allows you to cache the result of database queries and other async functions. To use it, wrap `unstable_cache` around the function. For example: | ||
|
||
```tsx filename="app/lib/data.ts swichter | ||
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]) | ||
} | ||
``` | ||
|
||
```jsx filename="app/lib/data.js" switcher | ||
import { db } from '@/lib/db' | ||
|
||
export async function getUserById(id) { | ||
return db | ||
.select() | ||
.from(users) | ||
.where(eq(users.id, id)) | ||
.then((res) => res[0]) | ||
} | ||
``` | ||
|
||
```tsx filename="app/page.tsx" highlight={2,11,13} switcher | ||
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 | ||
) | ||
} | ||
``` | ||
|
||
```jsx filename="app/page.jsx" highlight={2,7,9} switcher | ||
import { unstable_cache } from 'next/cache'; | ||
import { getUserById } from '@/app/lib/data'; | ||
|
||
export default async function Page({ params } }) { | ||
const { userId } = await params | ||
|
||
const getCachedUser = unstable_cache( | ||
async () => { | ||
return getUserById(userId) | ||
}, | ||
[userId] // add the user ID to the cache key | ||
); | ||
} | ||
``` | ||
|
||
The function accepts a third optional object to define how the cache should be revalidated. It accepts: | ||
|
||
- `tags`: an array of tags used by Next.js to revalidate the cache. | ||
- `revalidate`: the number of seconds after cache should be revalidated. | ||
|
||
```tsx filename="app/page.tsx" highlight={6-9} switcher | ||
const getCachedUser = unstable_cache( | ||
async () => { | ||
return getUserById(userId) | ||
}, | ||
[userId], | ||
{ | ||
tags: ['user'], | ||
revalidate: 3600, | ||
} | ||
) | ||
``` | ||
|
||
```jsx filename="app/page.js" highlight={6-9} switcher | ||
const getCachedUser = unstable_cache( | ||
async () => { | ||
return getUserById(userId) | ||
}, | ||
[userId], | ||
{ | ||
tags: ['user'], | ||
revalidate: 3600, | ||
} | ||
) | ||
``` | ||
|
||
See the [`unstable_cache` API reference](/docs/app/api-reference/functions/unstable_cache) to learn more. | ||
|
||
### `revalidateTag` | ||
|
||
`revalidateTag` is used to revalidate a cache entries based on a tag and following an event. To use it with `fetch`, start by tagging the function with the `next.tags` option: | ||
|
||
```tsx filename="app/lib/data.ts" highlight={3-5} switcher | ||
export async function getUserById(id: string) { | ||
const data = await fetch(`https://...`, { | ||
next: { | ||
tags: ['user'], | ||
}, | ||
}) | ||
} | ||
``` | ||
|
||
```jsx filename="app/lib/data.js" highlight={3-5} switcher | ||
export async function getUserById(id) { | ||
const data = await fetch(`https://...`, { | ||
next: { | ||
tags: ['user'], | ||
}, | ||
}) | ||
} | ||
``` | ||
|
||
Alternatively, you can mark an `unstable_cache` function with the `tags` option: | ||
|
||
```tsx filename="app/lib/data.ts" highlight={6-8} switcher | ||
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'], | ||
} | ||
) | ||
``` | ||
|
||
```jsx filename="app/lib/data.js" highlight={6-8} switcher | ||
export const getUserById = unstable_cache( | ||
async (id) => { | ||
return db.query.users.findFirst({ where: eq(users.id, id) }) | ||
}, | ||
['user'], // Needed if variables are not passed as parameters | ||
{ | ||
tags: ['user'], | ||
} | ||
) | ||
``` | ||
|
||
Then, call `revalidateTag` in a [Route Handler](/docs/app/api-reference/file-conventions/route) or Server Action: | ||
|
||
```tsx filename="app/lib/actions.ts" highlight={1} switcher | ||
import { revalidateTag } from 'next/cache' | ||
|
||
export async function updateUser(id: string) { | ||
// Mutate data | ||
revalidateTag('user') | ||
} | ||
``` | ||
|
||
```jsx filename="app/lib/actions.js" highlight={1} switcher | ||
import { revalidateTag } from 'next/cache' | ||
|
||
export async function updateUser(id) { | ||
// Mutate data | ||
revalidateTag('user') | ||
} | ||
``` | ||
|
||
You can reuse the same tag in multiple functions to revalidate them all at once. | ||
|
||
See the [`revalidateTag` API reference](/docs/app/api-reference/functions/revalidateTag) to learn more. | ||
|
||
### `revalidatePath` | ||
|
||
`revalidatePath` is used to revalidate a route and following an event. To use it, call it in a [Route Handler](/docs/app/api-reference/file-conventions/route) or Server Action: | ||
|
||
```tsx filename="app/lib/actions.ts" highlight={1} switcher | ||
import { revalidatePath } from 'next/cache' | ||
|
||
export async function updateUser(id: string) { | ||
// Mutate data | ||
revalidatePath('/profile') | ||
``` | ||
|
||
```jsx filename="app/lib/actions.js" highlight={1} switcher | ||
import { revalidatePath } from 'next/cache' | ||
|
||
export async function updateUser(id) { | ||
// Mutate data | ||
revalidatePath('/profile') | ||
``` | ||
|
||
See the [`revalidatePath` API reference](/docs/app/api-reference/functions/revalidatePath) to learn more. |
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.