Open Ingramz opened 1 month ago
I'm not sure if this counts as a bug, but the issue is that the vnode
of img
contains children
, which is unreasonable because the img
tag is self-closing and cannot have children
. Maybe we should ignore the children
of void tags when creating vnode.
You shouldn't add child nodes to the img tag, as it is unreasonable. You can modify it like this:
<template>
<component :is="node.name" v-if="node.type === 'element' && node.name !== 'img'" v-bind="node.attributes">
<ContentNode v-for="node2 in node.content" :node="node2" />
</component>
<template v-else-if="node.type === 'text'">{{ node.text }}</template>
<img v-else-if="node.name === 'img'" v-bind="node.attributes" />
</template>
Note: this will still report a mismatch in Playground because there is a bug in Playground, but it works correctly when the project is started locally.
Thank you for investigating, I can confirm that you are correct that creating a dedicated else-if branch for void elements with no content easily works around this. Playground reporting hydration mismatches despite not using a void element was driving me insane. 🤦
Also now that you explained that the img
vnode still contains children, then if I understand correctly, when comparing to the rendered HTML, which does not contain any children, it triggers the mismatch.
As for how to better handle this situation, I have no strong preference, but if the children on a void element vnode do not contribute to rendered HTML / DOM, they should be treated as valid and matching. If something visible was rendered, then that should still continue be treated as hydration mismatch due to the resulting HTML being invalid.
Vue version
3.5.11
Link to minimal reproduction
https://play.vuejs.org/#__SSR__eNqFVNtu00AQ/ZXBLwEptUnKTVZSCapKwEOpAPGCK+TYE2fLene1u3ZTRf53ZnxJ3CgKebAyZy4+M3PGu+CjMWFdYRAHC5dZYTw49JW5SpQojbYerrXyqPytzhHWVpcwCaMRxsmTRCUq08p5oCd7YAm/EwWw4weAfzIYwwQlluScTDtUpSWjZrBT761YVR5dDLumB/uCcVePf33NUV2P233RFiab4M8opYZHbWX+gih2vqHuqTpH/EYcRVmM0WdMwdmMQjbeGxdHUVqnPrUuLITfVKvKoe1bCDNdRlX0bjb/MHv9fjKFVDLLXxWGD24yIjZu+n6PDv4OYes+UYuoWxqtiwyPpZGpR7IAFrmoIZOpc8sk6AsmQesi53ir9cVaWwpSbAg1vD0JIGao95AZdYUjqkz/FtHofcE08I4S16KgbrQiPbXz5VeXRki034wXJJEkoJF1JJIgpQU9fm0xbyvsO6ScDWZ/T+APbstYEtxZpMHWRGrvo6EXSKTZffPjliQwcpY6ryRFn3F+R6dlxRy7sE+Vyon2KK5l+6W9CqGKn+5mS2NyQ1NMdNgMR9NdXJ9p/UD3MnzT5iWqoSkendbxXYJMVUEb8VSNxp7jWii8s9q4xQ54TTGk6gmaq5evzquD16IVn2osWCGcG7Laac/1hVgPEJ8GLJfLw3W0ASuh8iHkcA3/19ecBdZmnVbZfCSzPcXOHvhTPZQOT3JsvwTEYtcNI2QbmuaZVI91+6dGy1ukUV+Gb8PZLGj+AeRfpSE=
Steps to reproduce
Reproduction contains an example where a component called ContentNode references itself while rendering a tree of content elements. When enabling SSR, hydration mismatches are reported, but when comparing the generated HTML, everything seems OK.
What is expected?
No hydration mismatches.
What is actually happening?
Hydration mismatches are reported.
System Info
No response
Any additional comments?
No response