Skip to content

fix(hydration): log hydration error even when using async components #9403

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 22 additions & 13 deletions packages/runtime-core/src/hydration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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') &&
Expand Down Expand Up @@ -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 = (
Expand Down Expand Up @@ -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`,
Expand All @@ -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)
Expand Down Expand Up @@ -409,7 +413,6 @@ export function createHydrationFunctions(
)
let hasWarned = false
while (next) {
hasMismatch = true
if (
(__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) &&
!hasWarned
Expand All @@ -421,21 +424,24 @@ export function createHydrationFunctions(
)
hasWarned = true
}
logMismatchError()

// The SSRed DOM contains more nodes than it should. Remove them.
const cur = next
next = next.nextSibling
remove(cur)
}
} 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`,
el,
`\n - rendered on server: ${el.textContent}` +
`\n - expected on client: ${vnode.children as string}`,
)
logMismatchError()

el.textContent = vnode.children as string
}
}
Expand All @@ -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 &&
Expand Down Expand Up @@ -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
Expand All @@ -557,6 +562,8 @@ export function createHydrationFunctions(
)
hasWarned = true
}
logMismatchError()

// the SSRed DOM didn't contain enough nodes. Mount the missing ones.
patch(
null,
Expand Down Expand Up @@ -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
Expand All @@ -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:`,
Expand All @@ -631,6 +638,8 @@ export function createHydrationFunctions(
`\n- expected on client:`,
vnode.type,
)
logMismatchError()

vnode.el = null

if (isFragment) {
Expand Down