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
Lazy Hydration in Nuxt Core #24242
Comments
Hi All, Thank you very much for your great work! When using the directive approach, will the logic itself be lazy loaded in our bundle? Or even if we do not use it, it will increase the size? I am talking about the size of nuxt itself. Also will the component be available too? It seems kind of nice in some situations. |
Hey @yooneskh . I think a fair assumption would be to always code-split the lazy-loaded chunks. |
@filrak thanks for your response, i don't think i explained it correctly. What i though was that when the lazy hydration was a component, if we didn't use it, the logic for lazy hydrating a piece of the app would not be loaded (seperate from how that piece of the app will be loaded). But if it is a directive, we cannot treeshake the logic of lazy loading away. Kind of like how Vue 3 itself treeshakes parts of its functionalities away if they are not used. |
Great proposal! I also thought about this as a part of the core package. I would love it, and I think directives are the way to go in that subject. |
@yooneskh ok, I get your point now. Great question! I think the size of the directive itself will be insignificant, but I think the usage of the directive in the users' code can be easily detected during the build step. Therefore, it can be removed from the bundle if not used. There might be some obstacles I am unaware of, but for now, it seems entirely doable to me. |
I think it's a cool idea. Reminds me of astro style template directives |
@filrak That makes sense, thanks! |
Indeed, you posted it faster than me haha but here was the original discussion 👌🏻 That lead towards some custom API to create your own directives: https://docs.astro.build/en/reference/directives-reference/#custom-client-directives |
This API is awesome it's explicit and it's declarative. It even covers most of the use cases. |
This suggestion seems awesome! One thought: It might be useful to define a default hydration behaviour for a component, like making it a server component. e.g. hydrate:when-visible would be a reasonable default for a lot of components, maybe even a reasonable global default! Given different defaults, we'd have to add a hydrate:immediate option as well. |
Hi great suggestion, |
We'd like to explore expanding the ability of |
Describe the feature
What?
This proposal introduces lazy hydration feature as a first-class citizen in Nuxt Core.
Why?
Large JavaScript bundles are one of the key reasons behind poor performance of Single Page Applications. Every interactive element you add to the project at the component level is by default loaded eagerly during the application start-up, often blocking the critical rendering path.
The truth is - we rarely need interactivity upront. It's usually triggered - sometimes by an event like click, sometimes element appears in the viewport, sometimes it can be loaded when the browser is done with more important tasks and goes idle. Despite interactivity not being eagerly needed in most cases, we are lacking first-class solution allowing to control hydration process in Nuxt. There is a
<NuxtIsland>
component that moves the needle into the right direction but it's a 0/1 tool. If we're already going this direction, let's release a complete solution that tackles the problem as a whole.We see lazy hydration being implemented as a first-class citizen in (meta)frameworks like Astro or Qwik with great results that prove that interactivity is rarely needed eagerly.
We need similar solution in Nuxt, coming from the core, integrated well with other Nuxt features and benefiting from framework-level optimizations.
How?
A natural temptation would be to introduce components similar to the one from Vue3 Lazy Hydrate library but this solution is not perfect DX-wise.
When you have multiple components requireing different treating you end up doubling the size of your files by creating a separate wrapper for each component.
Here is an example from Vue Storefront's boilerplate for Nuxt 3.
A directive would be a much more elegant approach that fixes this small but definitely annoying DX flaw.
hydrate
directiveThe idea is simple - introduce global
hydrate
directive that can control when components are hydrated.Hydration callback
Having a hydration callback could make it easier to react to components hydration from it's parent.
It would be useful when we want to hydrate a set of compoennts in particular order.
Hydration Wrapper
We can use already existing
NuxtIsland
component to wrap multiple components/nodes at once.Framework-level optimizations
Thanks to component auto-imports we can statically analyze the code and specify which components chunks should be lazy-loaded as build-time optimization.
Additional information
Final checks
The text was updated successfully, but these errors were encountered: