]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(hydration): log hydration error even when using async components (#9403)
authorRodrigo Pimentel <47485736+RodrigoProjects@users.noreply.github.com>
Fri, 7 Jun 2024 07:45:16 +0000 (08:45 +0100)
committerGitHub <noreply@github.com>
Fri, 7 Jun 2024 07:45:16 +0000 (15:45 +0800)
close #9369

packages/runtime-core/src/hydration.ts

index 3be8837ce4b85751d891bbcfc4f70c217ee534b5..6fcf4dd4c2e2c98662b0eca1c64977b7837bba5c 100644 (file)
@@ -50,7 +50,15 @@ enum DOMNodeTypes {
   COMMENT = 8,
 }
 
-let hasMismatch = false
+let hasLoggedMismatchError = false
+const logMismatchError = () => {
+  if (__TEST__ || hasLoggedMismatchError) {
+    return
+  }
+  // this error should show up in production
+  console.error('Hydration completed but contains mismatches.')
+  hasLoggedMismatchError = true
+}
 
 const isSVGContainer = (container: Element) =>
   container.namespaceURI!.includes('svg') &&
@@ -102,14 +110,10 @@ export function createHydrationFunctions(
       container._vnode = vnode
       return
     }
-    hasMismatch = false
+
     hydrateNode(container.firstChild!, vnode, null, null, null)
     flushPostFlushCbs()
     container._vnode = vnode
-    if (hasMismatch && !__TEST__) {
-      // this error should show up in production
-      console.error(`Hydration completed but contains mismatches.`)
-    }
   }
 
   const hydrateNode = (
@@ -170,7 +174,6 @@ export function createHydrationFunctions(
           }
         } else {
           if ((node as Text).data !== vnode.children) {
-            hasMismatch = true
             ;(__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) &&
               warn(
                 `Hydration text mismatch in`,
@@ -180,6 +183,7 @@ export function createHydrationFunctions(
                 )}` +
                   `\n  - expected on client: ${JSON.stringify(vnode.children)}`,
               )
+            logMismatchError()
             ;(node as Text).data = vnode.children as string
           }
           nextNode = nextSibling(node)
@@ -409,7 +413,6 @@ export function createHydrationFunctions(
         )
         let hasWarned = false
         while (next) {
-          hasMismatch = true
           if (
             (__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) &&
             !hasWarned
@@ -421,6 +424,8 @@ export function createHydrationFunctions(
             )
             hasWarned = true
           }
+          logMismatchError()
+
           // The SSRed DOM contains more nodes than it should. Remove them.
           const cur = next
           next = next.nextSibling
@@ -428,7 +433,6 @@ export function createHydrationFunctions(
         }
       } else if (shapeFlag & ShapeFlags.TEXT_CHILDREN) {
         if (el.textContent !== vnode.children) {
-          hasMismatch = true
           ;(__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) &&
             warn(
               `Hydration text content mismatch on`,
@@ -436,6 +440,8 @@ export function createHydrationFunctions(
               `\n  - rendered on server: ${el.textContent}` +
                 `\n  - expected on client: ${vnode.children as string}`,
             )
+          logMismatchError()
+
           el.textContent = vnode.children as string
         }
       }
@@ -455,7 +461,7 @@ export function createHydrationFunctions(
               (__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) &&
               propHasMismatch(el, key, props[key], vnode, parentComponent)
             ) {
-              hasMismatch = true
+              logMismatchError()
             }
             if (
               (forcePatch &&
@@ -545,7 +551,6 @@ export function createHydrationFunctions(
         // because server rendered HTML won't contain a text node
         insert((vnode.el = createText('')), container)
       } else {
-        hasMismatch = true
         if (
           (__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) &&
           !hasWarned
@@ -557,6 +562,8 @@ export function createHydrationFunctions(
           )
           hasWarned = true
         }
+        logMismatchError()
+
         // the SSRed DOM didn't contain enough nodes. Mount the missing ones.
         patch(
           null,
@@ -603,7 +610,8 @@ export function createHydrationFunctions(
     } else {
       // fragment didn't hydrate successfully, since we didn't get a end anchor
       // back. This should have led to node/children mismatch warnings.
-      hasMismatch = true
+      logMismatchError()
+
       // since the anchor is missing, we need to create one and insert it
       insert((vnode.anchor = createComment(`]`)), container, next)
       return next
@@ -618,7 +626,6 @@ export function createHydrationFunctions(
     slotScopeIds: string[] | null,
     isFragment: boolean,
   ): Node | null => {
-    hasMismatch = true
     ;(__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) &&
       warn(
         `Hydration node mismatch:\n- rendered on server:`,
@@ -631,6 +638,8 @@ export function createHydrationFunctions(
         `\n- expected on client:`,
         vnode.type,
       )
+    logMismatchError()
+
     vnode.el = null
 
     if (isFragment) {