Skip to content
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

feat: lazy hydration #26468

Draft
wants to merge 85 commits into
base: main
Choose a base branch
from
Draft

Conversation

GalacticHypernova
Copy link
Contributor

πŸ”— Linked issue

#24242

❓ Type of change

  • πŸ“– Documentation (updates to the documentation, readme or JSdoc annotations)
  • 🐞 Bug fix (a non-breaking change that fixes an issue)
  • πŸ‘Œ Enhancement (improving an existing functionality like performance)
  • ✨ New feature (a non-breaking change that adds functionality)
  • 🧹 Chore (updates to the build process or auxiliary tools and libraries)
  • ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

πŸ“š Description

Lazy loading is a very beneficial addition to the nuxt core. Natively supporting delayed hydration will provide significant performance improvement. Moreover, it will reduce the amount of boilerplate code needed for manual implementations, and will reduce bundle size by not requiring external modules for something that may very well be handled out-of-the-box, as part of the Lazy components behavior.

πŸ“ Checklist

  • I have linked an issue or discussion.
  • I have added tests (if possible).
  • I have updated the documentation accordingly.

Copy link

stackblitz bot commented Mar 24, 2024

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

unobserve = null
})
return () => h('div', { ref: el }, [
isIntersecting.value ? h(componentLoader, attrs) : null,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to lazy hydrate or to lazy load here ?

Lazy hydration would need to render the component in SSR. Keep it "static"/non-interactive in client until loaded

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont actually know, which is better here? Do we want all of these wrappers to lazy load as opposed to lazy hydrate? Can this be lazy loaded via

h(await import(compName))

?
Or should the logic of defineAsyncComponent that we added in loader.ts be moved to inside the h?
From the current implementation I'm assuming it's lazily hydrated (please correct me if I'm wrong), but I suppose we should make performance tests to see which is better?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's more about how createClientIO should work.

The issue with the current state is that it is a client-only until observed because it is never rendered in SSR. So when missused, end users can experience a reduced UX (like when using CLientOnly). And also having an reduced webperf score if the lazyhydrated component is within the viewport at loading.

I think what #24242 was expecting is to render the component in SSR and then hydrate when observed.

So we could probably render the component in server side. Then until observed, it would be a static vnode (you can check how to do it in nuxt-island). Once observed, you'll be able to render the component.

I think the PR probably just need some changes within createClientIO

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Edit: didn't see you responded. I'll take a look at it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue with the current state is that it is a client-only until observed because it is never rendered in SSR. So when missused, end users can experience a reduced UX (like when using CLientOnly). And also having an reduced webperf score if the lazyhydrated component is within the viewport at loading.

Though the question here would be, would lazy loading not inherently provide better performance as opposed to lazy hydration? We can use a static vnode of course, but wouldn't lazy loading still reduce bundle? Of course everything can be misused, it's up to the individual developers to use the tools as intended.. There is no reason to make components inside the viewport async regardless, that in and of itself would hurt performance, even if it doesn't use any special wrappers. How can it hurt UX, especially if used properly?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's more about the meaning behind "lazy hydration", in my opinion it implies that the component is still rendered in SSR.

The current implementation is more like a "lazy component until in viewport" πŸ€” .

Though the question here would be, would lazy loading not inherently provide better performance as opposed to lazy hydration?

Probably slightly better with lazy loading. But rendering a static vnode isn't very costly in term of performance.

There is no reason to make components inside the viewport async regardless, that in and of itself would hurt performance, even if it doesn't use any special wrappers. How can it hurt UX, especially if used properly?

Indeed but some users may use it for a component that is in small breakpoint -> meaning that in desktop it would load the component after the page load resulting in some layout shift.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants