mirror of
https://github.com/hanzoai/next.js.git
synced 2026-09-24 17:00:51 +00:00
docs: draftMode alignment (#92794)
Closes: https://linear.app/vercel/issue/DOC-6291/draftmode-disables-cached-scopes-etc
This commit is contained in:
@@ -213,3 +213,67 @@ export default async function Page() {
|
||||
```
|
||||
|
||||
If you access the draft Route Handler (with `secret` and `slug`) from your headless CMS or manually using the URL, you should now be able to see the draft content. And, if you update your draft without publishing, you should be able to view the draft.
|
||||
|
||||
## Draft Mode with Cache Components
|
||||
|
||||
When using [caching directives](/docs/app/api-reference/directives/use-cache), Draft Mode forces all cached functions and components to produce fresh results on every request. You do not need to add any special handling to your caching code.
|
||||
|
||||
When Draft Mode is enabled:
|
||||
|
||||
- All functions and components under a caching directive scope re-execute on every request instead of serving from cache.
|
||||
- Results are not saved to the cache, so draft requests do not pollute cached content.
|
||||
- `fetch()` calls inside cached scopes use the original `fetch` implementation directly, without the Next.js fetch cache.
|
||||
- Response headers are set to `private, no-cache, no-store, max-age=0, must-revalidate`.
|
||||
|
||||
You can read if Draft Mode is enabled inside a caching directive scope, so you can conditionally fetch draft or published content:
|
||||
|
||||
```tsx filename="app/post/[slug]/page.tsx" switcher
|
||||
import { draftMode } from 'next/headers'
|
||||
|
||||
async function Post({ slug }: { slug: string }) {
|
||||
'use cache'
|
||||
|
||||
const { isEnabled } = await draftMode()
|
||||
|
||||
// Fetch draft or published content based on draft mode status
|
||||
const post = isEnabled
|
||||
? await fetchDraftPost(slug)
|
||||
: await fetchPublishedPost(slug)
|
||||
|
||||
return (
|
||||
<article>
|
||||
<h1>{post.title}</h1>
|
||||
<div>{post.content}</div>
|
||||
</article>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
```jsx filename="app/post/[slug]/page.js" switcher
|
||||
import { draftMode } from 'next/headers'
|
||||
|
||||
async function Post({ slug }) {
|
||||
'use cache'
|
||||
|
||||
const { isEnabled } = await draftMode()
|
||||
|
||||
// Fetch draft or published content based on draft mode status
|
||||
const post = isEnabled
|
||||
? await fetchDraftPost(slug)
|
||||
: await fetchPublishedPost(slug)
|
||||
|
||||
return (
|
||||
<article>
|
||||
<h1>{post.title}</h1>
|
||||
<div>{post.content}</div>
|
||||
</article>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
> **Good to know:**
|
||||
>
|
||||
> - You can await the `draftMode()` promise inside a caching directive scope to read `isEnabled`, but other runtime APIs like `cookies()` and `headers()` are not allowed and will throw an error, even when Draft Mode is active. (The [`"use cache: private"`](/docs/app/api-reference/directives/use-cache-private) directive does allow access to `cookies()` and `headers()`.)
|
||||
> - You cannot call `draftMode().enable()` or `draftMode().disable()` inside a caching directive scope. Draft Mode can only be toggled in [Route Handlers](/docs/app/api-reference/file-conventions/route) or [Server Actions](/docs/app/getting-started/mutating-data).
|
||||
|
||||
If your cached function needs values from `cookies()` or `headers()`, read them outside the caching directive scope and [pass them as arguments](/docs/app/getting-started/caching#passing-runtime-values-to-cached-functions).
|
||||
|
||||
@@ -210,6 +210,30 @@ If the default in-memory cache isn't enough, consider **[`use cache: remote`](/d
|
||||
|
||||
Very rarely, for compliance requirements or when you can't refactor your code to pass runtime data as arguments to a `use cache` scope, you might need [`use cache: private`](/docs/app/api-reference/directives/use-cache-private).
|
||||
|
||||
### Draft Mode
|
||||
|
||||
When [Draft Mode](/docs/app/guides/draft-mode) is enabled, all cached functions and components re-execute on every request, and results are not saved to the cache. This ensures draft content is always fresh without requiring any changes to your caching code.
|
||||
|
||||
You can read `isEnabled` from [`draftMode()`](/docs/app/api-reference/functions/draft-mode) inside a `use cache` scope, however, other runtime APIs like `cookies()` and `headers()` are not allowed, even when Draft Mode is active. See [Passing runtime values to cached functions](/docs/app/getting-started/caching#passing-runtime-values-to-cached-functions) for the recommended pattern.
|
||||
|
||||
```tsx filename="app/components/content.tsx"
|
||||
import { draftMode } from 'next/headers'
|
||||
|
||||
async function Content() {
|
||||
'use cache'
|
||||
|
||||
const { isEnabled } = await draftMode()
|
||||
const url = isEnabled
|
||||
? 'https://draft.example.com/content'
|
||||
: 'https://production.example.com/content'
|
||||
|
||||
const data = await fetch(url)
|
||||
return <article>{/* ... */}</article>
|
||||
}
|
||||
```
|
||||
|
||||
Calling `enable()` or `disable()` inside a caching directive scope will also throw an error. Draft Mode can only be toggled in [Route Handlers](/docs/app/api-reference/file-conventions/route) or [Server Actions](/docs/app/getting-started/mutating-data).
|
||||
|
||||
### React.cache isolation
|
||||
|
||||
[`React.cache`](https://react.dev/reference/react/cache) operates in an isolated scope inside `use cache` boundaries. Values stored via `React.cache` outside a `use cache` function are not visible inside it.
|
||||
|
||||
@@ -38,10 +38,13 @@ The following methods and properties are available:
|
||||
|
||||
## Good to know
|
||||
|
||||
- `draftMode` is an **asynchronous** function that returns a promise. You must use `async/await` or React's [`use`](https://react.dev/reference/react/use) function.
|
||||
- `draftMode` is an **asynchronous** function that returns a promise. You must use `async/await` or React’s [`use`](https://react.dev/reference/react/use) function.
|
||||
- In version 14 and earlier, `draftMode` was a synchronous function. To help with backwards compatibility, you can still access it synchronously in Next.js 15, but this behavior will be deprecated in the future.
|
||||
- A new bypass cookie value will be generated each time you run `next build`. This ensures that the bypass cookie can’t be guessed.
|
||||
- To test Draft Mode locally over HTTP, your browser will need to allow third-party cookies and local storage access.
|
||||
- [`isEnabled`](#checking-if-draft-mode-is-enabled) is readable inside a [caching directive](/docs/app/api-reference/directives/use-cache) scope. Other runtime APIs like `cookies()` and `headers()` are not allowed inside caching directive scopes, even when Draft Mode is active.
|
||||
- Calling `enable()` or `disable()` inside a caching directive scope will throw an error.
|
||||
- When Draft Mode is enabled, all functions and components under a caching directive scope re-execute on every request and results are not saved to the cache. This ensures draft content is always fresh.
|
||||
|
||||
## Examples
|
||||
|
||||
|
||||
Reference in New Issue
Block a user