Support for lazy hydration techniques: idle and view #52723
Replies: 4 comments 8 replies
-
Oh, I forgot one thing. Third-party store dependencyMaybe a third-party block requires the store of another block (namespace) which is lazy load and therefore may not be present from the beginning. Imagine a This is a tricky one because declaring a dependency on another block will fail if the block is not present on that page and declaring a dependency on another's block script will fail if the block owner refactores their files. I'll think about that 🙂 |
Beta Was this translation helpful? Give feedback.
-
I like the idea of how Astro did it. Would be cool if we can put media under the load JSON. In the future, Is it also possible to control CSS / stylesheet that is attached to the block as well? |
Beta Was this translation helpful? Give feedback.
-
So Since Astro uses Island Architecture. Have you checked Marko JS and QWIK JS? It's interesting what QWIK does in terms of partial hydration. Since I have posted before I feel that moving into Preact is the wrong approach if we are looking forward to the future, especially with Hydrations when we use the term "Interactivity" API. As you mentioned before Preact doesn't support upgrading from partially hydrated islands to a fully hydrated page yet. Maybe we should look into another framework. Hope this makes sense... |
Beta Was this translation helpful? Give feedback.
-
I just opened #58225 after finding that hydration can currently cause a long task which can significantly impact page performance, especially on lower-powered devices. I have a proposed fix in #58227 to break up the |
Beta Was this translation helpful? Give feedback.
-
It'd be great to delay the hydration of some of the interactive blocks to improve the time-to-interactive metrics of the site.
Hydrating on idle (CPU), when the block is about to enter the viewport, or only on certain screen sizes (media query) are techniques already used by frameworks like Astro. Rocket's implementation is also interesting. And we also implemented similar patterns in previous interactivity experiments.
Naming
"Hydration" is not a common term in WordPress, so my suggestion is to use "load" instead and refer to it as block loading techniques.
Configuring the loading technique
Maybe we could leverage the
data-wp-interactive
directive for this:Block developers could use the
block.json
"interactive"
field to add this information (which then will be added automatically to thedata-wp-interactive
directive):If they have options,
"load"
could accept an object:Combining techniques
Blocks could configure multiple loading techniques and the block would be hydrated when one of them triggers:
Code-split loading techniques
Ideally, we should code-split the code of each loading technique so we don't enqueue unnecessary JS.
loading-idle.js
fileloading-view.js
fileThe core runtime should only take care of hydrating the islands that don't have any special needs and don't do anything for the rest. Then, each loading technique file could take care of hydrating its own islands.
Download of scripts
Script download and execution should also be delayed. That means that for each lazy-loaded block, we should:
preload
/prefetch
(ormodulepreload
if we finally use modules).This means we need to know the source (or sources) of the scripts required by each block. We could also leverage
data-wp-interactive
for that:Having the scripts required for each block clearly stated in the HTML may also help when loading them for full-page client-side navigation.
Alternatively, we could use the enqueue ids instead of the URLs.
The order of execution would be something like this:
toVdom
and passes the result to Preact'srender
.Parent-child relationship
We need to decide if a child who wants to be hydrated before the parent should force the parent hydration, or if the first parent hydration technique should be enforced among all its children.
For example, imagine a child that wants to be hydrated before a parent because it's set to hydrate on idle whereas the parent block is set to hydrate on view:
My initial thought about this is that it's safer to force the parent hydration, but it may also lead to bad performance when a single child can force its parent and all siblings to hydrate.
If we decide that the parent should be forced to hydrate, we should do something like this:
And if we decide that the parent should not be forced to hydrate, we should do something like this:
Behaviors
Behaviors could also define their loading technique, and those should be accumulative.
Behaviors don't have a JSON yet, so this is just an example of how this could work in the future.
Available Techniques
I would probably start with idle and view, but other interesting ones could be developed in the future. Here is a tentative list:
Idle:
Load when the CPU is idle (
requestIdleCallback
).This is useful to avoid blocking the initial load of the page, and for blocks that will likely be used but are not critical.
View:
Load when the element enters the viewport.
One possible use case is to avoid loading the Comments Reply logic until the user is scrolling down and about to reach the comments.
Possible options are the Intersection Observer options, like
rootMargin
.Media:
Load only on certain media queries.
One possible use case is to avoid hydrating the Navigation block when the overlay menu is on
"mobile"
and it doesn't have submenus, and the user visits the page on a desktop computer.It needs a required query option, like
(max-width: 789px)
. Alternative names could be used to allow for preconfigured media queries, like"load": "mobile"
or"load": "desktop"
.Hover:
Load when the user hovers over the element.
One possible use case is to avoid loading the Image Lightbox behavior until the user is hovering over an image.
Loading techniques on full-page client-side navigation
Preact doesn't support upgrading from partially hydrated islands to a fully hydrated page yet (even with hacks) because changing the number of parent components in a tree after the initial hydration removes the children and adds them again unnecessarily. That means that the logic can't be reused, at least for now, when full-page client-side navigation is enabled, and therefore we need to take that into account when implementing each of the different parts.
Beta Was this translation helpful? Give feedback.
All reactions