Skip to content

Commit 3983741

Browse files
committed
fix(ssr): ensure empty slots render as comment nodes in hydration
1 parent cd9735d commit 3983741

File tree

4 files changed

+16
-9
lines changed

4 files changed

+16
-9
lines changed

packages/runtime-core/__tests__/hydration.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1681,7 +1681,7 @@ describe('SSR hydration', () => {
16811681
test('transition appear work with empty content', async () => {
16821682
const show = ref(true)
16831683
const { vnode, container } = mountWithHydration(
1684-
`<template></template>`,
1684+
`<template><!----></template>`,
16851685
function (this: any) {
16861686
return h(
16871687
Transition,
@@ -1696,7 +1696,7 @@ describe('SSR hydration', () => {
16961696
},
16971697
)
16981698

1699-
// expect empty slot render as a comment node
1699+
// empty slot render as a comment node
17001700
expect(container.firstChild!.nodeType).toBe(Node.COMMENT_NODE)
17011701
expect(vnode.el).toBe(container.firstChild)
17021702
expect(`mismatch`).not.toHaveBeenWarned()

packages/runtime-core/src/hydration.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -202,9 +202,7 @@ export function createHydrationFunctions(
202202
// wrapped <transition appear>
203203
// replace <template> node with inner child
204204
replaceNode(
205-
// #13394, the server may render an empty <template>, a comment node
206-
// needs to be created to be consistent with the client's behavior
207-
(vnode.el = node.content.firstChild || createComment('')),
205+
(vnode.el = node.content.firstChild!),
208206
node,
209207
parentComponent,
210208
)
@@ -399,11 +397,10 @@ export function createHydrationFunctions(
399397
parentComponent.vnode.props &&
400398
parentComponent.vnode.props.appear
401399

402-
let content =
403-
(el.content.firstChild as Element & { $cls?: string }) ||
404-
createComment('')
400+
let content = (el as HTMLTemplateElement).content
401+
.firstChild as Element & { $cls?: string }
405402

406-
if (needCallTransitionHooks && content instanceof Element) {
403+
if (needCallTransitionHooks) {
407404
const cls = content.getAttribute('class')
408405
if (cls) content.$cls = cls
409406
transition!.beforeEnter(content)

packages/server-renderer/__tests__/ssrSlot.spec.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,14 @@ describe('ssr: slot', () => {
124124
),
125125
).toBe(`<!---->`)
126126

127+
expect(
128+
await renderToString(
129+
createApp({
130+
template: `<transition><slot/></transition>`,
131+
}),
132+
),
133+
).toBe(`<!---->`)
134+
127135
expect(
128136
await renderToString(
129137
createApp({

packages/server-renderer/src/helpers/ssrRenderSlot.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ export function ssrRenderSlotInner(
117117
}
118118
} else if (fallbackRenderFn) {
119119
fallbackRenderFn()
120+
} else if (transition) {
121+
push(`<!---->`)
120122
}
121123
}
122124

0 commit comments

Comments
 (0)