diff --git a/packages/runtime-core/src/components/KeepAlive.ts b/packages/runtime-core/src/components/KeepAlive.ts index b6d04cbbac3..cbba10fd755 100644 --- a/packages/runtime-core/src/components/KeepAlive.ts +++ b/packages/runtime-core/src/components/KeepAlive.ts @@ -77,19 +77,26 @@ const KeepAliveImpl = { }, setup(props: KeepAliveProps, { slots }: SetupContext) { - const cache: Cache = new Map() - const keys: Keys = new Set() - let current: VNode | null = null - const instance = getCurrentInstance()! - const parentSuspense = instance.suspense - // KeepAlive communicates with the instantiated renderer via the // ctx where the renderer passes in its internals, // and the KeepAlive instance exposes activate/deactivate implementations. // The whole point of this is to avoid importing KeepAlive directly in the // renderer to facilitate tree-shaking. const sharedContext = instance.ctx as KeepAliveContext + + // if the internal renderer is not registered, it indicates that this is server-side rendering, + // for KeepAlive, we just need to render its children + if (!sharedContext.renderer) { + return slots.default + } + + const cache: Cache = new Map() + const keys: Keys = new Set() + let current: VNode | null = null + + const parentSuspense = instance.suspense + const { renderer: { p: patch, diff --git a/packages/server-renderer/__tests__/render.spec.ts b/packages/server-renderer/__tests__/render.spec.ts index 806ca210b23..37b35f6dea8 100644 --- a/packages/server-renderer/__tests__/render.spec.ts +++ b/packages/server-renderer/__tests__/render.spec.ts @@ -8,6 +8,7 @@ import { defineComponent, createTextVNode, createStaticVNode, + KeepAlive, withCtx } from 'vue' import { escapeHtml } from '@vue/shared' @@ -604,6 +605,17 @@ function testRender(type: string, render: typeof renderToString) { }) }) + describe('vnode component', () => { + test('KeepAlive', async () => { + const MyComp = { + render: () => h('p', 'hello') + } + expect(await render(h(KeepAlive, () => h(MyComp)))).toBe( + `
hello
` + ) + }) + }) + describe('raw vnode types', () => { test('Text', async () => { expect(await render(createTextVNode('hello