From 5493d60c4aecb697143ced84ba9c6b7c0b385933 Mon Sep 17 00:00:00 2001 From: Aaron_Zhou Date: Wed, 15 Nov 2023 00:56:31 +0800 Subject: [PATCH] fix(nuxt): provide route component names to `KeepAlive` cache (#24024) --- .../nuxt/src/app/components/route-provider.ts | 1 - packages/nuxt/src/pages/runtime/page.ts | 25 +++--- test/basic.test.ts | 81 +++++++++++++++++++ test/fixtures/basic/composables/keep-alive.ts | 6 ++ test/fixtures/basic/nuxt.config.ts | 3 + test/fixtures/basic/pages/keepalive.vue | 26 ++++++ .../pages/keepalive/keepalive-in-config.vue | 9 +++ .../keepalive/keepalive-in-nuxtpage-2.vue | 9 +++ .../pages/keepalive/keepalive-in-nuxtpage.vue | 9 +++ .../keepalive/not-keepalive-in-nuxtpage.vue | 9 +++ .../basic/pages/keepalive/not-keepalive.vue | 9 +++ 11 files changed, 177 insertions(+), 10 deletions(-) create mode 100644 test/fixtures/basic/composables/keep-alive.ts create mode 100644 test/fixtures/basic/pages/keepalive.vue create mode 100644 test/fixtures/basic/pages/keepalive/keepalive-in-config.vue create mode 100644 test/fixtures/basic/pages/keepalive/keepalive-in-nuxtpage-2.vue create mode 100644 test/fixtures/basic/pages/keepalive/keepalive-in-nuxtpage.vue create mode 100644 test/fixtures/basic/pages/keepalive/not-keepalive-in-nuxtpage.vue create mode 100644 test/fixtures/basic/pages/keepalive/not-keepalive.vue diff --git a/packages/nuxt/src/app/components/route-provider.ts b/packages/nuxt/src/app/components/route-provider.ts index 5111eafec8..6f57fb82f6 100644 --- a/packages/nuxt/src/app/components/route-provider.ts +++ b/packages/nuxt/src/app/components/route-provider.ts @@ -4,7 +4,6 @@ import type { RouteLocation, RouteLocationNormalizedLoaded } from '#vue-router' import { PageRouteSymbol } from './injections' export const RouteProvider = defineComponent({ - name: 'RouteProvider', props: { vnode: { type: Object as () => VNode, diff --git a/packages/nuxt/src/pages/runtime/page.ts b/packages/nuxt/src/pages/runtime/page.ts index 0661be00cf..9c97d02b77 100644 --- a/packages/nuxt/src/pages/runtime/page.ts +++ b/packages/nuxt/src/pages/runtime/page.ts @@ -88,20 +88,27 @@ export default defineComponent({ { onAfterLeave: () => { nuxtApp.callHook('page:transition:finish', routeProps.Component) } } ].filter(Boolean)) + const keepaliveConfig = props.keepalive ?? routeProps.route.meta.keepalive ?? (defaultKeepaliveConfig as KeepAliveProps) vnode = _wrapIf(Transition, hasTransition && transitionProps, - wrapInKeepAlive(props.keepalive ?? routeProps.route.meta.keepalive ?? (defaultKeepaliveConfig as KeepAliveProps), h(Suspense, { + wrapInKeepAlive(keepaliveConfig, h(Suspense, { suspensible: true, onPending: () => nuxtApp.callHook('page:start', routeProps.Component), onResolve: () => { nextTick(() => nuxtApp.callHook('page:finish', routeProps.Component).finally(done)) } }, { - default: () => h(RouteProvider, { - key: key || undefined, - vnode: routeProps.Component, - route: routeProps.route, - renderKey: key || undefined, - trackRootNodes: hasTransition, - vnodeRef: pageRef - }) + default: () => { + const providerVNode = h(RouteProvider, { + key: key || undefined, + vnode: routeProps.Component, + route: routeProps.route, + renderKey: key || undefined, + trackRootNodes: hasTransition, + vnodeRef: pageRef + }) + if (import.meta.client && keepaliveConfig) { + (providerVNode.type as any).name = (routeProps.Component.type as any).name || (routeProps.Component.type as any).__name || 'RouteProvider' + } + return providerVNode + } }) )).default() diff --git a/test/basic.test.ts b/test/basic.test.ts index d4386c9086..31e3d919e7 100644 --- a/test/basic.test.ts +++ b/test/basic.test.ts @@ -2017,6 +2017,87 @@ describe.runIf(isDev())('component testing', () => { }) }) +describe('keepalive', () => { + it('should not keepalive by default', async () => { + const { page, consoleLogs } = await renderPage('/keepalive') + + const pageName = 'not-keepalive' + await page.click(`#${pageName}`) + await page.waitForTimeout(25) + + expect(consoleLogs.map(l => l.text).filter(t => t.includes('keepalive'))).toEqual([`${pageName}: onMounted`]) + + await page.close() + }) + + it('should not keepalive when included in app config but config in nuxt-page is not undefined', async () => { + const { page, consoleLogs } = await renderPage('/keepalive') + + const pageName = 'keepalive-in-config' + await page.click(`#${pageName}`) + await page.waitForTimeout(25) + + expect(consoleLogs.map(l => l.text).filter(t => t.includes('keepalive'))).toEqual([`${pageName}: onMounted`]) + + await page.close() + }) + + it('should not keepalive when included in app config but exclueded in nuxt-page', async () => { + const { page, consoleLogs } = await renderPage('/keepalive') + + const pageName = 'not-keepalive-in-nuxtpage' + await page.click(`#${pageName}`) + await page.waitForTimeout(25) + + expect(consoleLogs.map(l => l.text).filter(t => t.includes('keepalive'))).toEqual([`${pageName}: onMounted`]) + + await page.close() + }) + + it('should keepalive when included in nuxt-page', async () => { + const { page, consoleLogs } = await renderPage('/keepalive') + + const pageName = 'keepalive-in-nuxtpage' + await page.click(`#${pageName}`) + await page.waitForTimeout(25) + + expect(consoleLogs.map(l => l.text).filter(t => t.includes('keepalive'))).toEqual([`${pageName}: onMounted`, `${pageName}: onActivated`]) + + await page.close() + }) + + it('should preserve keepalive config when navigate routes in nuxt-page', async () => { + const { page, consoleLogs } = await renderPage('/keepalive') + + await page.click('#keepalive-in-nuxtpage') + await page.waitForTimeout(25) + await page.click('#keepalive-in-nuxtpage-2') + await page.waitForTimeout(25) + await page.click('#keepalive-in-nuxtpage') + await page.waitForTimeout(25) + await page.click('#not-keepalive') + await page.waitForTimeout(25) + await page.click('#keepalive-in-nuxtpage-2') + await page.waitForTimeout(25) + + expect(consoleLogs.map(l => l.text).filter(t => t.includes('keepalive'))).toEqual([ + 'keepalive-in-nuxtpage: onMounted', + 'keepalive-in-nuxtpage: onActivated', + 'keepalive-in-nuxtpage: onDeactivated', + 'keepalive-in-nuxtpage-2: onMounted', + 'keepalive-in-nuxtpage-2: onActivated', + 'keepalive-in-nuxtpage: onActivated', + 'keepalive-in-nuxtpage-2: onDeactivated', + 'keepalive-in-nuxtpage: onDeactivated', + 'not-keepalive: onMounted', + 'keepalive-in-nuxtpage-2: onActivated', + 'not-keepalive: onUnmounted' + ]) + + await page.close() + }) +}) + function normaliseIslandResult (result: NuxtIslandResponse) { return { ...result, diff --git a/test/fixtures/basic/composables/keep-alive.ts b/test/fixtures/basic/composables/keep-alive.ts new file mode 100644 index 0000000000..bee308628e --- /dev/null +++ b/test/fixtures/basic/composables/keep-alive.ts @@ -0,0 +1,6 @@ +export function useLifecyleLogs (name: string) { + onMounted(() => console.log(`${name}: onMounted`)) + onUnmounted(() => console.log(`${name}: onUnmounted`)) + onActivated(() => console.log(`${name}: onActivated`)) + onDeactivated(() => console.log(`${name}: onDeactivated`)) +} diff --git a/test/fixtures/basic/nuxt.config.ts b/test/fixtures/basic/nuxt.config.ts index 570b54b62b..5b6d6e469a 100644 --- a/test/fixtures/basic/nuxt.config.ts +++ b/test/fixtures/basic/nuxt.config.ts @@ -22,6 +22,9 @@ export default defineNuxtConfig({ { charset: 'utf-8' }, { name: 'description', content: 'Nuxt Fixture' } ] + }, + keepalive: { + include: ['keepalive-in-config', 'not-keepalive-in-nuxtpage'] } }, buildDir: process.env.NITRO_BUILD_DIR, diff --git a/test/fixtures/basic/pages/keepalive.vue b/test/fixtures/basic/pages/keepalive.vue new file mode 100644 index 0000000000..fdaa673a94 --- /dev/null +++ b/test/fixtures/basic/pages/keepalive.vue @@ -0,0 +1,26 @@ + + + diff --git a/test/fixtures/basic/pages/keepalive/keepalive-in-config.vue b/test/fixtures/basic/pages/keepalive/keepalive-in-config.vue new file mode 100644 index 0000000000..a057e7427b --- /dev/null +++ b/test/fixtures/basic/pages/keepalive/keepalive-in-config.vue @@ -0,0 +1,9 @@ + + + diff --git a/test/fixtures/basic/pages/keepalive/keepalive-in-nuxtpage-2.vue b/test/fixtures/basic/pages/keepalive/keepalive-in-nuxtpage-2.vue new file mode 100644 index 0000000000..bb4fd440c2 --- /dev/null +++ b/test/fixtures/basic/pages/keepalive/keepalive-in-nuxtpage-2.vue @@ -0,0 +1,9 @@ + + + diff --git a/test/fixtures/basic/pages/keepalive/keepalive-in-nuxtpage.vue b/test/fixtures/basic/pages/keepalive/keepalive-in-nuxtpage.vue new file mode 100644 index 0000000000..19c4312cca --- /dev/null +++ b/test/fixtures/basic/pages/keepalive/keepalive-in-nuxtpage.vue @@ -0,0 +1,9 @@ + + + diff --git a/test/fixtures/basic/pages/keepalive/not-keepalive-in-nuxtpage.vue b/test/fixtures/basic/pages/keepalive/not-keepalive-in-nuxtpage.vue new file mode 100644 index 0000000000..6d16f7173d --- /dev/null +++ b/test/fixtures/basic/pages/keepalive/not-keepalive-in-nuxtpage.vue @@ -0,0 +1,9 @@ + + + diff --git a/test/fixtures/basic/pages/keepalive/not-keepalive.vue b/test/fixtures/basic/pages/keepalive/not-keepalive.vue new file mode 100644 index 0000000000..e7fc57ea43 --- /dev/null +++ b/test/fixtures/basic/pages/keepalive/not-keepalive.vue @@ -0,0 +1,9 @@ + + +