From b7516a13929c66ea56cffa5443dbebf13c2b58f7 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Fri, 8 Mar 2024 17:03:38 +0000 Subject: [PATCH] fix(nuxt): access prerender cache synchronously (#26146) --- packages/nuxt/src/app/composables/asyncData.ts | 6 +++--- packages/nuxt/src/app/nuxt.ts | 2 +- packages/nuxt/src/core/nitro.ts | 4 +++- packages/nuxt/src/core/runtime/nitro/renderer.ts | 13 +++++++------ 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/packages/nuxt/src/app/composables/asyncData.ts b/packages/nuxt/src/app/composables/asyncData.ts index 79a7813ba9..f5c2c18a16 100644 --- a/packages/nuxt/src/app/composables/asyncData.ts +++ b/packages/nuxt/src/app/composables/asyncData.ts @@ -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 } const promise = nuxtApp.runWithContext(_handler) nuxtApp.ssrContext!._sharedPrerenderCache!.set(key, promise) diff --git a/packages/nuxt/src/app/nuxt.ts b/packages/nuxt/src/app/nuxt.ts index ce515d6a8b..8c069985ba 100644 --- a/packages/nuxt/src/app/nuxt.ts +++ b/packages/nuxt/src/app/nuxt.ts @@ -73,7 +73,7 @@ export interface NuxtSSRContext extends SSRContext { _payloadReducers: Record any> /** @internal */ _sharedPrerenderCache?: { - get (key: string): Promise + get (key: string): Promise | undefined set (key: string, value: Promise): Promise } } diff --git a/packages/nuxt/src/core/nitro.ts b/packages/nuxt/src/core/nitro.ts index 9bb9fddfa9..e2a1ee456a 100644 --- a/packages/nuxt/src/core/nitro.ts +++ b/packages/nuxt/src/core/nitro.ts @@ -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 } }) diff --git a/packages/nuxt/src/core/runtime/nitro/renderer.ts b/packages/nuxt/src/core/runtime/nitro/renderer.ts index 3d262a1e3d..e1fabfb458 100644 --- a/packages/nuxt/src/core/runtime/nitro/renderer.ts +++ b/packages/nuxt/src/core/runtime/nitro/renderer.ts @@ -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>() : null +const sharedPrerenderKeys = new Set() const sharedPrerenderCache = import.meta.prerender && process.env.NUXT_SHARED_DATA ? { - get (key: string): Promise { - if (sharedPrerenderPromises!.has(key)) { - return sharedPrerenderPromises!.get(key)! + get (key: string): Promise | undefined { + if (sharedPrerenderKeys.has(key)) { + return sharedPrerenderPromises!.get(key) ?? useStorage('internal:nuxt:prerender:shared').getItem(key) as Promise } - return useStorage('internal:nuxt:prerender:shared').getItem(key) as Promise }, - async set (key: string, value: Promise) { + async set (key: string, value: Promise): Promise { + 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)) },