- 
          
- 
                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 <33403762+rschristian@users.noreply.github.com> refactor: reorder template tag check to avoid expensive instanceof first Co-authored-by: Ryan Christian <33403762+rschristian@users.noreply.github.com> 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/hydratelogic 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.