-
-
Notifications
You must be signed in to change notification settings - Fork 2k
fix: reuse DOM nodes inside <template> during hydration #4803
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
base: main
Are you sure you want to change the base?
fix: reuse DOM nodes inside <template> during hydration #4803
Conversation
📊 Tachometer Benchmark ResultsSummaryduration
usedJSHeapSize
Resultscreate10kduration
usedJSHeapSize
filter-listduration
usedJSHeapSize
hydrate1kduration
usedJSHeapSize
many-updatesduration
usedJSHeapSize
replace1kduration
usedJSHeapSize
run-warmup-0
run-warmup-1
run-warmup-2
run-warmup-3
run-warmup-4
run-final
text-updateduration
usedJSHeapSize
tododuration
usedJSHeapSize
update10th1kduration
usedJSHeapSize
|
Size Change: +120 B (+0.26%) Total Size: 46.8 kB
ℹ️ View Unchanged
|
fix: apply precommit hook Co-authored-by: Ryan Christian <[email protected]> refactor: reorder template tag check to avoid expensive instanceof first Co-authored-by: Ryan Christian <[email protected]> fix: import slice from util file
16b8b19
to
1dae489
Compare
Thanks for the review — commits have been squashed. |
if ( | ||
newParentVNode.type === 'template' && | ||
excessDomChildren?.length === 0 && | ||
parentDom instanceof DocumentFragment | ||
) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's make this fast by adding the isHydrating
check, we don't need to check excessDomChildren
length as we expect this to be 0 as per your assumptions in this PR. I would assume that we are in a DocumentFragment when we are dealing with a template.
if ( | |
newParentVNode.type === 'template' && | |
excessDomChildren?.length === 0 && | |
parentDom instanceof DocumentFragment | |
) { | |
if (isHydrating && newParentVNode.type === 'template') { |
I assume you could save even more bytes by moving this to
Lines 596 to 611 in 1dae489
diffChildren( | |
// @ts-expect-error | |
newVNode.type == 'template' ? dom.content : dom, | |
isArray(newChildren) ? newChildren : [newChildren], | |
newVNode, | |
oldVNode, | |
globalContext, | |
nodeType == 'foreignObject' ? XHTML_NAMESPACE : namespace, | |
excessDomChildren, | |
commitQueue, | |
excessDomChildren | |
? excessDomChildren[0] | |
: oldVNode._children && getDomSibling(oldVNode, 0), | |
isHydrating, | |
refQueue | |
); |
newVNode.type === 'template'
as well as hoisting the duplicated check
fix 3732
When hydrating a
<template>
element, Preact fails to reuse existing DOM nodes insidetemplate.content
.This is because
<template>
elements encapsulate their children within aDocumentFragment
, but thediff
/hydrate
logic doesn't switch the context totemplate.content
.As a result, hydration skips the existing fragment content and instead appends new nodes — leading to duplicated content in the DOM.