fix(nuxt): access prerender cache synchronously (#26146)

This commit is contained in:
Daniel Roe 2024-03-08 17:03:38 +00:00 committed by GitHub
parent 6407cea620
commit b7516a1392
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 14 additions and 11 deletions

View File

@ -214,9 +214,9 @@ export function useAsyncData<
const nuxtApp = useNuxtApp()
// When prerendering, share payload data automatically between requests
const handler = import.meta.client || !import.meta.prerender || !nuxtApp.ssrContext?._sharedPrerenderCache ? _handler : async () => {
const value = await nuxtApp.ssrContext!._sharedPrerenderCache!.get(key)
if (value) { return value as ResT }
const handler = import.meta.client || !import.meta.prerender || !nuxtApp.ssrContext?._sharedPrerenderCache ? _handler : () => {
const value = nuxtApp.ssrContext!._sharedPrerenderCache!.get(key)
if (value) { return value as Promise<ResT> }
const promise = nuxtApp.runWithContext(_handler)
nuxtApp.ssrContext!._sharedPrerenderCache!.set(key, promise)

View File

@ -73,7 +73,7 @@ export interface NuxtSSRContext extends SSRContext {
_payloadReducers: Record<string, (data: any) => any>
/** @internal */
_sharedPrerenderCache?: {
get<T = unknown> (key: string): Promise<T>
get<T = unknown> (key: string): Promise<T> | undefined
set<T> (key: string, value: Promise<T>): Promise<void>
}
}

View File

@ -393,10 +393,12 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
}
})
const cacheDir = resolve(nuxt.options.buildDir, 'cache/nitro/prerender')
await fsp.rm(cacheDir, { recursive: true, force: true }).catch(() => {})
nitro.options._config.storage = defu(nitro.options._config.storage, {
'internal:nuxt:prerender': {
driver: pathToFileURL(await resolvePath(join(distDir, 'core/runtime/nitro/cache-driver'))).href,
base: resolve(nuxt.options.buildDir, 'cache/nitro/prerender')
base: cacheDir
}
})

View File

@ -185,16 +185,17 @@ const payloadCache = import.meta.prerender ? useStorage('internal:nuxt:prerender
const islandCache = import.meta.prerender ? useStorage('internal:nuxt:prerender:island') : null
const islandPropCache = import.meta.prerender ? useStorage('internal:nuxt:prerender:island-props') : null
const sharedPrerenderPromises = import.meta.prerender && process.env.NUXT_SHARED_DATA ? new Map<string, Promise<any>>() : null
const sharedPrerenderKeys = new Set<string>()
const sharedPrerenderCache = import.meta.prerender && process.env.NUXT_SHARED_DATA ? {
get <T = unknown>(key: string): Promise<T> {
if (sharedPrerenderPromises!.has(key)) {
return sharedPrerenderPromises!.get(key)!
get <T = unknown>(key: string): Promise<T> | undefined {
if (sharedPrerenderKeys.has(key)) {
return sharedPrerenderPromises!.get(key) ?? useStorage('internal:nuxt:prerender:shared').getItem(key) as Promise<T>
}
return useStorage('internal:nuxt:prerender:shared').getItem(key) as Promise<T>
},
async set <T>(key: string, value: Promise<T>) {
async set <T>(key: string, value: Promise<T>): Promise<void> {
sharedPrerenderKeys.add(key)
sharedPrerenderPromises!.set(key, value)
return useStorage('internal:nuxt:prerender:shared').setItem(key, await value as any)
useStorage('internal:nuxt:prerender:shared').setItem(key, await value as any)
// free up memory after the promise is resolved
.finally(() => sharedPrerenderPromises!.delete(key))
},