From: daiwei Date: Tue, 5 Aug 2025 07:13:07 +0000 (+0800) Subject: wip: process component as a single element during hydration X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=bd5d341ffebab13627e435ab19ecbcc92325917f;p=thirdparty%2Fvuejs%2Fcore.git wip: process component as a single element during hydration --- diff --git a/packages/compiler-ssr/__tests__/ssrElement.spec.ts b/packages/compiler-ssr/__tests__/ssrElement.spec.ts index d344405f3e..57e4f022c0 100644 --- a/packages/compiler-ssr/__tests__/ssrElement.spec.ts +++ b/packages/compiler-ssr/__tests__/ssrElement.spec.ts @@ -409,9 +409,9 @@ describe('ssr: element', () => { `), ).toMatchInlineSnapshot(` - "\`
\`) + "\`
\`) _push(_ssrRenderComponent(_component_Comp1, null, null, _parent)) - _push(\`\`) + _push(\`\`) _push(_ssrRenderComponent(_component_Comp2, null, null, _parent)) _push(\`
\`" `) @@ -430,15 +430,15 @@ describe('ssr: element', () => {
`), ).toMatchInlineSnapshot(` - "\`
\`) + "\`
\`) _push(_ssrRenderComponent(_component_Comp1, null, null, _parent)) - _push(\`\`) + _push(\`\`) _push(_ssrRenderComponent(_component_Comp2, null, null, _parent)) _push(\`\`) _push(_ssrRenderComponent(_component_Comp3, null, null, _parent)) - _push(\`\`) + _push(\`\`) _push(_ssrRenderComponent(_component_Comp4, null, null, _parent)) - _push(\`
\`" + _push(\`
\`" `) }) }) diff --git a/packages/compiler-ssr/src/ssrCodegenTransform.ts b/packages/compiler-ssr/src/ssrCodegenTransform.ts index 852e02820c..80329aaab7 100644 --- a/packages/compiler-ssr/src/ssrCodegenTransform.ts +++ b/packages/compiler-ssr/src/ssrCodegenTransform.ts @@ -197,7 +197,11 @@ export function processChildren( ssrProcessElement(child, context) break case ElementTypes.COMPONENT: + if (inElement) + context.pushStringPart(``) ssrProcessComponent(child, context, parent) + if (inElement) + context.pushStringPart(``) break case ElementTypes.SLOT: ssrProcessSlotOutlet(child, context) diff --git a/packages/runtime-core/__tests__/hydration.spec.ts b/packages/runtime-core/__tests__/hydration.spec.ts index 092df4738a..418d37cc8a 100644 --- a/packages/runtime-core/__tests__/hydration.spec.ts +++ b/packages/runtime-core/__tests__/hydration.spec.ts @@ -713,7 +713,7 @@ describe('SSR hydration', () => { // server render container.innerHTML = await renderToString(h(App)) expect(container.innerHTML).toBe( - '
', + '
', ) expect(teleportContainer1.innerHTML).toBe('') expect(teleportContainer2.innerHTML).toBe('') @@ -721,7 +721,7 @@ describe('SSR hydration', () => { // hydrate createSSRApp(App).mount(container) expect(container.innerHTML).toBe( - '
', + '
', ) expect(teleportContainer1.innerHTML).toBe('Teleported') expect(teleportContainer2.innerHTML).toBe('') @@ -1005,7 +1005,7 @@ describe('SSR hydration', () => { // server render container.innerHTML = await renderToString(h(App)) expect(container.innerHTML).toMatchInlineSnapshot( - `"
12
"`, + `"
12
"`, ) // reset asyncDeps from ssr asyncDeps.length = 0 @@ -1923,14 +1923,14 @@ describe('SSR hydration', () => { const root = document.createElement('div') root.innerHTML = await renderToString(h(App)) createSSRApp(App).mount(root) - expect(root.innerHTML).toBe('
foo
') + expect(root.innerHTML).toBe('
foo
') reload(id, { __hmrId: id, template: `
bar
`, }) await nextTick() - expect(root.innerHTML).toBe('
bar
') + expect(root.innerHTML).toBe('
bar
') }) test('hmr root reload', async () => { diff --git a/packages/runtime-vapor/__tests__/hydration.spec.ts b/packages/runtime-vapor/__tests__/hydration.spec.ts index 86c110e203..5ff4cbf51f 100644 --- a/packages/runtime-vapor/__tests__/hydration.spec.ts +++ b/packages/runtime-vapor/__tests__/hydration.spec.ts @@ -276,13 +276,13 @@ describe('Vapor Mode hydration', () => { { Child: `` }, ) expect(container.innerHTML).toMatchInlineSnapshot( - `"
foo
"`, + `"
foo
"`, ) data.value = 'bar' await nextTick() expect(container.innerHTML).toMatchInlineSnapshot( - `"
bar
"`, + `"
bar
"`, ) }) @@ -294,13 +294,13 @@ describe('Vapor Mode hydration', () => { { Child: `` }, ) expect(container.innerHTML).toMatchInlineSnapshot( - `"
foo
-foo-
"`, + `"
foo
-foo-
"`, ) data.value = 'bar' await nextTick() expect(container.innerHTML).toMatchInlineSnapshot( - `"
bar
-bar-
"`, + `"
bar
-bar-
"`, ) }) @@ -312,13 +312,13 @@ describe('Vapor Mode hydration', () => { { Child: `` }, ) expect(container.innerHTML).toMatchInlineSnapshot( - `"
foo
-foo-
"`, + `"
foo
-foo-
"`, ) data.value = 'bar' await nextTick() expect(container.innerHTML).toMatchInlineSnapshot( - `"
bar
-bar-
"`, + `"
bar
-bar-
"`, ) }) @@ -334,11 +334,11 @@ describe('Vapor Mode hydration', () => { ) expect(container.innerHTML).toBe( `
` + - `` + + `` + `
` + `
foo
-foo-` + `
` + - `` + + `` + `` + `
`, ) @@ -347,11 +347,11 @@ describe('Vapor Mode hydration', () => { await nextTick() expect(container.innerHTML).toBe( `
` + - `` + + `` + `
` + `
bar
-bar-` + `
` + - `` + + `` + `` + `
`, ) @@ -372,13 +372,13 @@ describe('Vapor Mode hydration', () => { }, ) expect(container.innerHTML).toMatchInlineSnapshot( - `"
foo
"`, + `"
foo
"`, ) data.value = 'bar' await nextTick() expect(container.innerHTML).toMatchInlineSnapshot( - `"
bar
"`, + `"
bar
"`, ) }) @@ -393,13 +393,13 @@ describe('Vapor Mode hydration', () => { }, ) expect(container.innerHTML).toBe( - `
foo
`, + `
foo
`, ) data.value = 'bar' await nextTick() expect(container.innerHTML).toBe( - `
bar
`, + `
bar
`, ) }) @@ -416,11 +416,11 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `
` + + `
` + `` + - `
foo
` + + `
foo
` + `` + - `
` + + `
` + `` + `
`, ) @@ -430,11 +430,11 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `
` + + `
` + `` + - `
bar
` + + `
bar
` + `` + - `
` + + `
` + `` + `
`, ) @@ -458,7 +458,7 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `foo` + + `foo` + `foo` + `` + `
`, @@ -469,7 +469,7 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `bar` + + `bar` + `bar` + `` + `
`, @@ -493,14 +493,14 @@ describe('Vapor Mode hydration', () => { data, ) expect(container.innerHTML).toBe( - `
foobar
`, + `
foobar
`, ) data.foo = 'foo1' data.bar = 'bar1' await nextTick() expect(container.innerHTML).toBe( - `
foo1bar1
`, + `
foo1bar1
`, ) }) @@ -517,7 +517,7 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `
foo
` + + `
foo
` + `
foo
` + `` + `
`, @@ -528,7 +528,7 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `
bar
` + + `
bar
` + `
bar
` + `` + `
`, @@ -548,12 +548,12 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `
` + + `
` + `` + - `
foo
` + + `
foo
` + `
foo
` + `` + - `
` + + `
` + `` + `
`, ) @@ -563,12 +563,12 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `
` + + `
` + `` + - `
bar
` + + `
bar
` + `
bar
` + `` + - `
` + + `
` + `` + `
`, ) @@ -593,9 +593,9 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `foo` + + `foo` + `` + - `foo` + + `foo` + `` + `
`, ) @@ -605,9 +605,9 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `bar` + + `bar` + `` + - `bar` + + `bar` + `` + `
`, ) @@ -632,9 +632,9 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `foo` + - ` foo ` + - `foo` + + `foo` + + ` foo ` + + `foo` + `` + `
`, ) @@ -644,9 +644,9 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `bar` + - ` bar ` + - `bar` + + `bar` + + ` bar ` + + `bar` + `` + `
`, ) @@ -669,7 +669,7 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `
foo
-foo` + + `
foo
-foo` + `` + `
`, ) @@ -679,7 +679,7 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `
bar
-bar` + + `
bar
-bar` + `` + `
`, ) @@ -698,7 +698,7 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `
foo
-foo-` + + `
foo
-foo-` + `` + `
`, ) @@ -708,7 +708,7 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `
bar
-bar-` + + `
bar
-bar-` + `` + `
`, ) @@ -727,11 +727,11 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `
` + + `
` + `` + - `
foo
-foo-` + + `
foo
-foo-` + `` + - `
` + + `
` + `` + `
`, ) @@ -741,11 +741,11 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `
` + + `
` + `` + - `
bar
-bar-` + + `
bar
-bar-` + `` + - `
` + + `
` + `` + `
`, ) @@ -769,10 +769,8 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `
foo
-foo` + - `` + - `
foo
-foo` + - `` + + `
foo
-foo` + + `
foo
-foo` + `` + `
`, ) @@ -782,10 +780,8 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `
bar
-bar` + - `` + - `
bar
-bar` + - `` + + `
bar
-bar` + + `
bar
-bar` + `` + `
`, ) @@ -804,10 +800,8 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `
foo
-foo-` + - `` + - `
foo
-foo-` + - `` + + `
foo
-foo-` + + `
foo
-foo-` + `` + `
`, ) @@ -817,10 +811,8 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `
bar
-bar-` + - `` + - `
bar
-bar-` + - `` + + `
bar
-bar-` + + `
bar
-bar-` + `` + `
`, ) @@ -839,14 +831,12 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `
` + + `
` + `` + - `
foo
-foo-` + - `` + - `
foo
-foo-` + - `` + + `
foo
-foo-` + + `
foo
-foo-` + `` + - `
` + + `
` + `` + `
`, ) @@ -856,14 +846,12 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `
` + + `
` + `` + - `
bar
-bar-` + - `` + - `
bar
-bar-` + - `` + + `
bar
-bar-` + + `
bar
-bar-` + `` + - `
` + + `
` + `` + `
`, ) @@ -882,10 +870,10 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `` + + `` + `
foo
-foo-` + `
foo
-foo-` + - `` + + `` + `` + `
`, ) @@ -895,10 +883,10 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `` + + `` + `
bar
-bar-` + `
bar
-bar-` + - `` + + `` + `` + `
`, ) @@ -923,9 +911,9 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `
foo
-foo` + + `
foo
-foo` + `` + - `
foo
-foo` + + `
foo
-foo` + `` + `
`, ) @@ -935,9 +923,9 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `
bar
-bar` + + `
bar
-bar` + `` + - `
bar
-bar` + + `
bar
-bar` + `` + `
`, ) @@ -962,9 +950,9 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `
foo
-foo` + + `
foo
-foo` + ` foo ` + - `
foo
-foo` + + `
foo
-foo` + `` + `
`, ) @@ -974,9 +962,9 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `
bar
-bar` + + `
bar
-bar` + ` bar ` + - `
bar
-bar` + + `
bar
-bar` + `` + `
`, ) @@ -1022,7 +1010,7 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `
foo
` + + `
foo
` + `` + `
`, ) @@ -1032,7 +1020,7 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `
bar
` + + `
bar
` + `` + `
`, ) @@ -1057,7 +1045,7 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `
foo
` + + `
foo
` + `
foo
` + `` + `
`, @@ -1068,7 +1056,7 @@ describe('Vapor Mode hydration', () => { expect(container.innerHTML).toBe( `
` + `` + - `
bar
` + + `
bar
` + `
bar
` + `` + `
`, @@ -1145,7 +1133,9 @@ describe('Vapor Mode hydration', () => { { Child: `` }, data, ) - expect(container.innerHTML).toBe(`
foo
`) + expect(container.innerHTML).toBe( + `
foo
`, + ) data.value = false await nextTick() @@ -1481,8 +1471,8 @@ describe('Vapor Mode hydration', () => { ) expect(container.innerHTML).toBe( `
` + - `foo` + - `bar` + + `foo` + + `bar` + `
` + ``, ) @@ -2335,9 +2325,9 @@ describe('Vapor Mode hydration', () => { ) expect(container.innerHTML).toBe( `
` + - `
bar
` + + `
bar
` + `foo` + - `
bar
` + + `
bar
` + `
`, ) @@ -2345,9 +2335,9 @@ describe('Vapor Mode hydration', () => { await nextTick() expect(container.innerHTML).toBe( `
` + - `
hello
` + + `
hello
` + `foo` + - `
hello
` + + `
hello
` + `
`, ) }) @@ -2381,9 +2371,9 @@ describe('Vapor Mode hydration', () => { ) expect(container.innerHTML).toBe( `
` + - `
foo
bar` + + `
foo
bar` + `foo` + - `
foo
bar` + + `
foo
bar` + `
`, ) @@ -2392,9 +2382,9 @@ describe('Vapor Mode hydration', () => { await nextTick() expect(container.innerHTML).toBe( `
` + - `
hello
vapor` + + `
hello
vapor` + `hello` + - `
hello
vapor` + + `
hello
vapor` + `
`, ) }) @@ -2667,14 +2657,14 @@ describe('Vapor Mode hydration', () => { ) expect(container.innerHTML).toBe( `
` + - `
` + - `
` + + `
` + + `
` + `` + `foo` + `` + `` + - `
` + - `
` + + `
` + + `
` + `
bar
` + `
`, ) @@ -2684,14 +2674,14 @@ describe('Vapor Mode hydration', () => { await nextTick() expect(container.innerHTML).toBe( `
` + - `
` + - `
` + + `
` + + `
` + `` + `foo1` + `` + `` + - `
` + - `
` + + `
` + + `
` + `
bar1
` + `
`, ) diff --git a/packages/runtime-vapor/src/dom/hydration.ts b/packages/runtime-vapor/src/dom/hydration.ts index 0186300585..1f4df1f454 100644 --- a/packages/runtime-vapor/src/dom/hydration.ts +++ b/packages/runtime-vapor/src/dom/hydration.ts @@ -12,7 +12,7 @@ import { disableHydrationNodeLookup, enableHydrationNodeLookup, } from './node' -import { isVaporAnchors } from '@vue/shared' +import { DYNAMIC_END_ANCHOR_LABEL, isVaporAnchors } from '@vue/shared' export let isHydrating = false export let currentHydrationNode: Node | null = null @@ -23,15 +23,22 @@ export function setCurrentHydrationNode(node: Node | null): void { function findParentSibling(n: Node): Node | null { if (!n.parentNode) return null - const next = n.parentNode.nextSibling + let next = n.parentNode.nextSibling + while (next && isComment(next, DYNAMIC_END_ANCHOR_LABEL)) { + next = next.nextElementSibling + } return next ? next : findParentSibling(n.parentNode) } export function advanceHydrationNode(node: Node & { $ps?: Node | null }): void { + let next = node.nextSibling + while (next && isComment(next, DYNAMIC_END_ANCHOR_LABEL)) { + next = next.nextSibling + } + // if no next sibling, find the next node in the parent chain - const next = - node.nextSibling || node.$ps || (node.$ps = findParentSibling(node)) - if (next) setCurrentHydrationNode(next) + const ret = next || node.$ps || (node.$ps = findParentSibling(node)) + if (ret) setCurrentHydrationNode(ret) } let isOptimized = false