Update cache handling in draft mode (#51663)
Similar to `getStaticProps` when draft mode is enabled we should bypass the cache so fresh data is shown. x-ref: [slack thread](https://vercel.slack.com/archives/C052BQ8F9EJ/p1687440125828479?thread_ts=1684336597.437409&cid=C052BQ8F9EJ) and [tweet](https://twitter.com/tomus_sherman/status/1669023879656873988) --------- Co-authored-by: Steven <steven@ceriously.com>
This commit is contained in:
parent
82abde8dd9
commit
f749684921
6 changed files with 63 additions and 2 deletions
|
@ -45,6 +45,8 @@ export interface StaticGenerationStore {
|
|||
status: number
|
||||
cacheStatus: 'hit' | 'miss'
|
||||
}>
|
||||
|
||||
isDraftMode?: boolean
|
||||
}
|
||||
|
||||
export type StaticGenerationAsyncStorage =
|
||||
|
|
|
@ -69,6 +69,8 @@ export const StaticGenerationAsyncStorageWrapper: AsyncStorageWrapper<
|
|||
isPrerendering: renderOpts.nextExport,
|
||||
fetchCache: renderOpts.fetchCache,
|
||||
isOnDemandRevalidate: renderOpts.isOnDemandRevalidate,
|
||||
|
||||
isDraftMode: renderOpts.isDraftMode,
|
||||
}
|
||||
|
||||
// TODO: remove this when we resolve accessing the store outside the execution context
|
||||
|
|
|
@ -126,7 +126,11 @@ export function patchFetch({
|
|||
// If the staticGenerationStore is not available, we can't do any
|
||||
// special treatment of fetch, therefore fallback to the original
|
||||
// fetch implementation.
|
||||
if (!staticGenerationStore || (init?.next as any)?.internal) {
|
||||
if (
|
||||
!staticGenerationStore ||
|
||||
(init?.next as any)?.internal ||
|
||||
staticGenerationStore.isDraftMode
|
||||
) {
|
||||
return originFetch(input, init)
|
||||
}
|
||||
|
||||
|
|
|
@ -465,6 +465,7 @@ createNextDescribe(
|
|||
|
||||
expect(files).toEqual([
|
||||
'(new)/custom/page.js',
|
||||
'api/draft-mode/route.js',
|
||||
'api/revalidate-path-edge/route.js',
|
||||
'api/revalidate-path-node/route.js',
|
||||
'api/revalidate-tag-edge/route.js',
|
||||
|
@ -1139,6 +1140,37 @@ createNextDescribe(
|
|||
})
|
||||
}
|
||||
|
||||
it('should skip cache in draft mode', async () => {
|
||||
const draftRes = await next.fetch('/api/draft-mode?status=enable')
|
||||
const setCookie = draftRes.headers.get('set-cookie')
|
||||
const cookieHeader = { Cookie: setCookie?.split(';')[0] }
|
||||
|
||||
expect(cookieHeader.Cookie).toBeTruthy()
|
||||
|
||||
const res = await next.fetch('/ssg-draft-mode/test-1', {
|
||||
headers: cookieHeader,
|
||||
})
|
||||
|
||||
const html = await res.text()
|
||||
const $ = cheerio.load(html)
|
||||
const data1 = $('#data').text()
|
||||
|
||||
expect(data1).toBeTruthy()
|
||||
expect(JSON.parse($('#draft-mode').text())).toEqual({ isEnabled: true })
|
||||
|
||||
const res2 = await next.fetch('/ssg-draft-mode/test-1', {
|
||||
headers: cookieHeader,
|
||||
})
|
||||
|
||||
const html2 = await res2.text()
|
||||
const $2 = cheerio.load(html2)
|
||||
const data2 = $2('#data').text()
|
||||
|
||||
expect(data2).toBeTruthy()
|
||||
expect(data1).not.toBe(data2)
|
||||
expect(JSON.parse($2('#draft-mode').text())).toEqual({ isEnabled: true })
|
||||
})
|
||||
|
||||
it('should handle partial-gen-params with default dynamicParams correctly', async () => {
|
||||
const res = await next.fetch('/partial-gen-params/en/first')
|
||||
expect(res.status).toBe(200)
|
||||
|
|
16
test/e2e/app-dir/app-static/app/api/draft-mode/route.ts
Normal file
16
test/e2e/app-dir/app-static/app/api/draft-mode/route.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
import { draftMode } from 'next/headers'
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
|
||||
export function GET(req: NextRequest) {
|
||||
const status = req.nextUrl.searchParams.get('status')
|
||||
|
||||
if (status === 'enable') {
|
||||
draftMode().enable()
|
||||
} else {
|
||||
draftMode().disable()
|
||||
}
|
||||
|
||||
return NextResponse.json({
|
||||
status,
|
||||
})
|
||||
}
|
|
@ -1,11 +1,16 @@
|
|||
import { draftMode } from 'next/headers'
|
||||
|
||||
export default function Page() {
|
||||
export default async function Page() {
|
||||
const data = await fetch(
|
||||
'https://next-data-api-endpoint.vercel.app/api/random'
|
||||
).then((res) => res.text())
|
||||
|
||||
const { isEnabled } = draftMode()
|
||||
|
||||
return (
|
||||
<main>
|
||||
<pre id="draft-mode">{JSON.stringify({ isEnabled })}</pre>
|
||||
<p id="data">{data}</p>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue