Explorar el Código

fix(ssr): fix hydration mismatch when entire multi-root template is stringified

fix #6637
Evan You hace 3 años
padre
commit
9698dd3cf1

+ 8 - 0
packages/runtime-core/__tests__/hydration.spec.ts

@@ -982,6 +982,14 @@ describe('SSR hydration', () => {
     expect((container as any)._vnode).toBe(null)
   })
 
+  // #6637
+  test('stringified root fragment', () => {
+    mountWithHydration(`<!--[--><div></div><!--]-->`, () =>
+      createStaticVNode(`<div></div>`, 1)
+    )
+    expect(`mismatch`).not.toHaveBeenWarned()
+  })
+
   describe('mismatch handling', () => {
     test('text node', () => {
       const { container } = mountWithHydration(`foo`, () => 'bar')

+ 10 - 5
packages/runtime-core/src/hydration.ts

@@ -108,7 +108,7 @@ export function createHydrationFunctions(
       )
 
     const { type, ref, shapeFlag, patchFlag } = vnode
-    const domType = node.nodeType
+    let domType = node.nodeType
     vnode.el = node
 
     if (patchFlag === PatchFlags.BAIL) {
@@ -150,9 +150,12 @@ export function createHydrationFunctions(
         }
         break
       case Static:
-        if (domType !== DOMNodeTypes.ELEMENT && domType !== DOMNodeTypes.TEXT) {
-          nextNode = onMismatch()
-        } else {
+        if (isFragmentStart) {
+          // entire template is static but SSRed as a fragment
+          node = nextSibling(node)!
+          domType = node.nodeType
+        }
+        if (domType === DOMNodeTypes.ELEMENT || domType === DOMNodeTypes.TEXT) {
           // determine anchor, adopt content
           nextNode = node
           // if the static vnode has its content stripped during build,
@@ -169,7 +172,9 @@ export function createHydrationFunctions(
             }
             nextNode = nextSibling(nextNode)!
           }
-          return nextNode
+          return isFragmentStart ? nextSibling(nextNode) : nextNode
+        } else {
+          onMismatch()
         }
         break
       case Fragment: