-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Interactivity API: Defer hydration until node is scrolled near the viewport #58284
base: trunk
Are you sure you want to change the base?
Changes from 15 commits
645c945
6ac9d62
cffdb4d
4cc10a7
3770575
1f845c9
d0587db
cfe2b04
d580cce
fb15565
3ec8de5
6b95333
5532ee4
08720c4
d27985e
88d679c
abd3747
387ab6c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -29,6 +29,38 @@ export const initialVdom = new WeakMap< Element, ComponentChild[] >(); | |||||||||||||||||||||||||
|
||||||||||||||||||||||||||
// Initialize the router with the initial DOM. | ||||||||||||||||||||||||||
export const init = async () => { | ||||||||||||||||||||||||||
const pendingNodes = new Set(); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
const intersectionObserver = new window.IntersectionObserver( | ||||||||||||||||||||||||||
async ( entries ) => { | ||||||||||||||||||||||||||
for ( const entry of entries ) { | ||||||||||||||||||||||||||
if ( ! entry.isIntersecting ) { | ||||||||||||||||||||||||||
continue; | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
const node = entry.target; | ||||||||||||||||||||||||||
intersectionObserver.unobserve( node ); | ||||||||||||||||||||||||||
pendingNodes.delete( node ); | ||||||||||||||||||||||||||
if ( pendingNodes.size === 0 ) { | ||||||||||||||||||||||||||
intersectionObserver.disconnect(); | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
if ( ! hydratedIslands.has( node ) ) { | ||||||||||||||||||||||||||
const fragment = getRegionRootFragment( node ); | ||||||||||||||||||||||||||
const vdom = toVdom( node ); | ||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the old logic, this used to populate There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems this is a merge conflict resolution on my part. This may be needed: --- a/packages/interactivity/src/init.ts
+++ b/packages/interactivity/src/init.ts
@@ -48,6 +48,7 @@ export const init = async () => {
if ( ! hydratedIslands.has( node ) ) {
const fragment = getRegionRootFragment( node );
const vdom = toVdom( node );
+ initialVdom.set( node, vdom );
await splitTask();
hydrate( vdom, fragment );
await splitTask(); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like it is only being used here: gutenberg/packages/interactivity-router/src/index.ts Lines 189 to 200 in ef7afef
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Introduced in #58496 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Restored I found that this code in @DAreRodz For this page cache, is it a problem that |
||||||||||||||||||||||||||
await splitTask(); | ||||||||||||||||||||||||||
hydrate( vdom, fragment ); | ||||||||||||||||||||||||||
await splitTask(); | ||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why does this yield at the end of the process? In the original code that happened before, right above the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As I recall, I moved it here because given that this is now inside of an |
||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||
root: null, // To watch for intersection relative to the device's viewport. | ||||||||||||||||||||||||||
rootMargin: '100% 0% 100% 0%', // Intersect when within 1 viewport approaching from top or bottom. | ||||||||||||||||||||||||||
threshold: 0.0, // As soon as even one pixel is visible. | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
const nodes = document.querySelectorAll( | ||||||||||||||||||||||||||
`[data-${ directivePrefix }-interactive]` | ||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||
|
@@ -45,13 +77,7 @@ export const init = async () => { | |||||||||||||||||||||||||
} ); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
for ( const node of nodes ) { | ||||||||||||||||||||||||||
if ( ! hydratedIslands.has( node ) ) { | ||||||||||||||||||||||||||
await splitTask(); | ||||||||||||||||||||||||||
const fragment = getRegionRootFragment( node ); | ||||||||||||||||||||||||||
const vdom = toVdom( node ); | ||||||||||||||||||||||||||
initialVdom.set( node, vdom ); | ||||||||||||||||||||||||||
await splitTask(); | ||||||||||||||||||||||||||
hydrate( vdom, fragment ); | ||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
pendingNodes.add( node ); | ||||||||||||||||||||||||||
intersectionObserver.observe( node ); | ||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it might be a good idea to keep the
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||
}; |
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.
If I understand correctly, the
pendingNodes
variable is only being populated to check this? I guess there's no way to check if theintersectionObserver
is "empty"?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.
That's right. There is no "observed count" exposed on the
IntersectionObserver
interface. We could change this to instead be a simple counter.This should have the same effect, with a slight benefit that the element references wouldn't be stored in the
Set
, meaning that there wouldn't be the possibility of a memory leak. (I should have used aWeakSet
here originally, probably.)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.
Added in abd3747