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