N
Nuxtโ€ข3w ago
Mubo

Is it possible to use 'hydrate-never' with '<component :is="....' ?

Is it possible to use 'hydrate-never' with '<component :is="....' ? When we tried using it like this the 'hydrate-never' part got ignored and it was working the same as before. Is there any workaround for this ? We would like to use dynamic pages/components with the new delayed hydration feature.
16 Replies
kapa.ai
kapa.aiโ€ข3w ago
Hi @Mubo. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Based on the knowledge sources, there are some limitations with using delayed hydration in Nuxt, particularly with dynamic components. Currently, Nuxt's built-in lazy hydration has specific constraints: 1. It only works in single-file components (SFCs) 2. It requires you to define the hydration prop directly in the template (rather than spreading via v-bind) 3. It does not work with direct imports from #components As mentioned in the documentation: "Currently Nuxt's built-in lazy hydration only works in single-file components (SFCs), and requires you to define the prop in the template (rather than spreading an object of props via v-bind)." Delayed Hydration Documentation The issue you're experiencing with hydrate-never being ignored when used with dynamic components (<component :is="...") aligns with these limitations. The dynamic component resolution happens at runtime, while the hydration strategies need to be determined during the build process. For a workaround, you have a few options: 1. Use a predefined map of components with their hydration strategies already applied:
const componentMap = {
key1: resolveComponent('MyComponentA'), // with hydrate-never applied to the component itself
key2: resolveComponent('MyComponentB'),
key3: resolveComponent('MyComponentC'),
}
const getComponent = (key) => {
return componentMap[key]
}
const componentMap = {
key1: resolveComponent('MyComponentA'), // with hydrate-never applied to the component itself
key2: resolveComponent('MyComponentB'),
key3: resolveComponent('MyComponentC'),
}
const getComponent = (key) => {
return componentMap[key]
}
2. Make your components global (though this has performance implications):
<template>
<component :is="componentName" hydrate-never />
</template>
<template>
<component :is="componentName" hydrate-never />
</template>
This works only if the component is registered globally, as mentioned in the Stack Overflow post about dynamic components in Nuxt 3. 3. Consider using the new lazy hydration macros that were recently introduced (in PR #31192), which provide an explicit import solution:
<script setup lang="ts">
const LazyHydrationMyComponent = defineLazyHydrationComponent(
'never',
() => import('./components/MyComponent.vue')
)
</script>
<template>
<div>
<!-- This component will never be hydrated by Vue. -->
<LazyHydrationMyComponent />
</div>
</template>
<script setup lang="ts">
const LazyHydrationMyComponent = defineLazyHydrationComponent(
'never',
() => import('./components/MyComponent.vue')
)
</script>
<template>
<div>
<!-- This component will never be hydrated by Vue. -->
<LazyHydrationMyComponent />
</div>
</template>
However, this is a newer feature and may not be available in your current Nuxt version. The core issue is that the dynamic component resolution with :is doesn't properly integrate with the hydration strategies in the current implementation. This is a known limitation of how Nuxt processes these special hydration props. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.aiโ€ข3w ago
<@659047750381338624> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Mubo
MuboOPโ€ข3w ago
I did try points 1. and 2. and it didnt work. I will try point 3. Maybe another solution would be to write v-if for all of the components in the template and add Lazy prefix to them with correct hydration what do you think @kapa.ai @kapa.ai
kapa.ai
kapa.aiโ€ข3w ago
Let me check the knowledge base for you again. One moment! :books: Sorry @Mubo, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist: Perhaps try again in 15mins?
manniL
manniLโ€ข3w ago
I don't think so @Mubo as the component name can't be inferred. You'd have to do it manually I think
manniL
manniLโ€ข3w ago
Nuxt
components/ ยท Nuxt Directory Structure
The components/ directory is where you put all your Vue components.
Mubo
MuboOPโ€ข3w ago
Thank you @manniL ๐Ÿ™Œ
dataexcess
dataexcessโ€ข3w ago
sorry can someone explain to me what the solution is? I'm stuck with the same problem I tried having a simple empty component called 'Page' with a slot.. I then would wrap my <component :is> components in a LazyPage... but that does not seem to work either @manniL could you take a look at my question? would appreciate it a lot. big fan of your channel ๐Ÿ˜€
manniL
manniLโ€ข3w ago
thanks! ๐Ÿ™ The answer is - you can't with component :is directly you need to use an SFC regarding slots & no component :is: that might be sth. to raise, but a similar issue exists
dataexcess
dataexcessโ€ข2w ago
@manniL Not sure if I understand... but I'll paste some code here. The main issue I want to solve is this: I have a one-page vertical scroll website with different sections. Since I am so used to working with Nuxt /pages directory I thought it'd be a good idea to keep using the pages directory and to transform the pages into components. But in doing so I am having a difficult time to make those components lazy... I guess I could solve it in using components instead of transformed pages for this and prefixing 'Lazy-' but I was wondering what you think about this ๐Ÿ˜„
<template>
<div class="relative h-[100svh] w-full bg-white">
<main class="absolute inset-0 h-full w-fulloverflow-y-auto px-6">
<component
v-for="(page, idx) in pages"
:is="page.component"
:key="idx"
/>
</main>
</div>
</template>

<script setup>
const pages = [
{ path: '/', component: defineAsyncComponent(() => import('@/pages/landing.vue')) },
{ path: '/volume1', component: defineAsyncComponent(() => import('@/pages/volume1.vue')) },
{ path: '/books', component: defineAsyncComponent(() => import('@/pages/books.vue')) },
{ path: '/about', component: defineAsyncComponent(() => import('@/pages/about.vue')) }
]
</script>
<template>
<div class="relative h-[100svh] w-full bg-white">
<main class="absolute inset-0 h-full w-fulloverflow-y-auto px-6">
<component
v-for="(page, idx) in pages"
:is="page.component"
:key="idx"
/>
</main>
</div>
</template>

<script setup>
const pages = [
{ path: '/', component: defineAsyncComponent(() => import('@/pages/landing.vue')) },
{ path: '/volume1', component: defineAsyncComponent(() => import('@/pages/volume1.vue')) },
{ path: '/books', component: defineAsyncComponent(() => import('@/pages/books.vue')) },
{ path: '/about', component: defineAsyncComponent(() => import('@/pages/about.vue')) }
]
</script>
manniL
manniLโ€ข2w ago
yeah, it won't work with componen :is You need to use an auto import and it needs to be "statically analyzable"
manniL
manniLโ€ข2w ago
if you use defineAsyncComponent manually, you can use Vue's lazy hydration directly or wait for https://github.com/nuxt/nuxt/pull/31192
GitHub
feat(nuxt): support lazy hydration macros by Mini-ghost ยท Pull Req...
๐Ÿ”— Linked issue ๐Ÿ“š Description This PR introduces a few macros to provide an explicit import solution for lazy hydration. TODO Macro plugin (LazyHydrationMacroTransformPlugin) Type support Docume...
dataexcess
dataexcessโ€ข2w ago
do you mean the hydration field in the defineAsyncComponent API ? it seems it's not exposed in nuxt
import { defineAsyncComponent, hydrateOnVisible } from 'vue'

const AsyncComp = defineAsyncComponent({
loader: () => import('./Comp.vue'),
hydrate: hydrateOnVisible()
})
import { defineAsyncComponent, hydrateOnVisible } from 'vue'

const AsyncComp = defineAsyncComponent({
loader: () => import('./Comp.vue'),
hydrate: hydrateOnVisible()
})
` do you mean importing the Component manually? like we would do without nuxt's auto import? Sorry I'm a bit noobish in these concepts ๐Ÿ˜ฆ
manniL
manniLโ€ข2w ago
Yes, that should work. The only downside is that you'd have to "remove" the javascript being loaded manually. https://github.com/nuxt/nuxt/pull/31192 should solve both issues actually
GitHub
feat(nuxt): support lazy hydration macros by Mini-ghost ยท Pull Req...
๐Ÿ”— Linked issue ๐Ÿ“š Description This PR introduces a few macros to provide an explicit import solution for lazy hydration. TODO Macro plugin (LazyHydrationMacroTransformPlugin) Type support Docume...
manniL
manniLโ€ข2w ago
no no, manual imports don't work either. What I mean is that right now, a static string in the template + auto import is necessary. The linked PR offers an explicit solution
dataexcess
dataexcessโ€ข2w ago
ok so you're saying it basically does not work for dynamic / runtime defined components..? Ah yes - the component needs to be able to be auto imported for it to work - (known as a type by nuxt) I get it now hmmm ok I guess I could checkout on that feature branch... OR i could simply drop the pages directory and use components instead :p

Did you find this page helpful?