diff --git a/packages/server-renderer/__tests__/ssrSlot.spec.ts b/packages/server-renderer/__tests__/ssrSlot.spec.ts index 4534630879f..7e2b2247d25 100644 --- a/packages/server-renderer/__tests__/ssrSlot.spec.ts +++ b/packages/server-renderer/__tests__/ssrSlot.spec.ts @@ -137,4 +137,20 @@ describe('ssr: slot', () => { ), ).toBe(`
foo
`) }) + + // #9933 + test('transition-group slot', async () => { + expect( + await renderToString( + createApp({ + components: { + one: { + template: ``, + }, + }, + template: `

{{i}}

`, + }), + ), + ).toBe(`

1

2

`) + }) }) diff --git a/packages/server-renderer/src/helpers/ssrRenderSlot.ts b/packages/server-renderer/src/helpers/ssrRenderSlot.ts index b388e7d1936..df088e8929a 100644 --- a/packages/server-renderer/src/helpers/ssrRenderSlot.ts +++ b/packages/server-renderer/src/helpers/ssrRenderSlot.ts @@ -82,7 +82,23 @@ export function ssrRenderSlotInner( fallbackRenderFn() } } else { - for (let i = 0; i < slotBuffer.length; i++) { + // #9933 + // Although we handle Transition/TransitionGroup in the transform stage + // without rendering it as a fragment, the content passed into the slot + // may still be a fragment. + // Therefore, here we need to avoid rendering it as a fragment again. + let start = 0 + let end = slotBuffer.length + if ( + transition && + slotBuffer[0] === '' && + slotBuffer[end - 1] === '' + ) { + start++ + end-- + } + + for (let i = start; i < end; i++) { push(slotBuffer[i]) } }