SSR hydration mismatches
Describe the bug
I added all the playground components to nuxt to test SSR, and noticed 53 warning, most of which were about hydration missmatches.
The reproduction on stackblitz doesn't generate that many warnings.
We should figure out a better way to test ssr.
Reproduction
https://stackblitz.com/edit/nuxt-starter-lqee3m?file=layouts%2Fdefault.vue
Used Package Manager
pnpm
Validations
- [X] Have tested with the latest version. This is still alpha version and sometime things change rapidly.
- [X] Follow our Code of Conduct
- [X] Read the Contributing Guide.
- [X] Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
- [X] Check that this is a concrete bug. For Q&A, please open a GitHub Discussion instead.
- [X] The provided reproduction is a minimal reproducible of the bug.
Hi,
I've just updated a nuxt project from 0.14.10 to the latest 0.15.5 and also found a few "hydration mismatches" that weren't present before.
Tried downgrading versions and apparently the issues started right from v0.15.0.
Issues seems to be something to do with BButton inside BDropdown. See two examples below:
[Vue warn]: Hydration children mismatch in <div>: server rendered element contains fewer child nodes than client vdom.
at <BButton id="__BVID__498027___BV_dropdown__" ref_key="splitButton" ref=Ref< null > ... >
at <BDropdown ref_key="dropdown" ref=Ref< null > ariaLabel=undefined ... >
at <BNavItemDropdown class="text-nowrap me-2 me-md-0" menu-class="bg-body-tertiary position-absolute border-5 border-ltgreen border-top-0 z-3 py-0 rounded-3 rounded-top-0 langdd" toggle-class="d-flex align-items-center" ... >
at <BNavbarNav class="fs-5" >
(...)
[Vue warn]: Hydration children mismatch in <div>: server rendered element contains fewer child nodes than client vdom.
at <BButton id="selpax" ref_key="splitButton" ref=Ref< null > ... >
at <BDropdown menu-class="shadow p-2" id="selpax" auto-close="outside" ... >
(...)
Hope it helps, cheers.
@ptdev could you create a little example on stackblitz? just fork this and make it fail like you have? That would help me to focus on your problem and maybe find it faster.
edit: oh, the stacklitz was using the 0.14 and that's why I couldn't make it fail :) now it's erroring about hydration.
@VividLemon It seems all the components that use Teleport are not working in nuxt. Should I convert the teleports back to RenderComponentOrSkip component? I can't get teleport to work in our components, it works directly in nuxt if I import the component from ../bootstra-vue-next/src, but not the dist version.
edit: got it. in nuxt if you have :to="refThatIsUndefined" nuxt will skip the whole render.
got Failed to execute 'querySelector' on 'Document': The provided selector is empty. if :to="''" on teleport
fixed in #1652
Hey,
Sure, here is a simplified sample of what i'm using.
But note that even without modification, your stackblitz link already shows an hydration error (at least on my end :) )
Thanks, cheers! 👍
@ptdev this will be fixed in 0.16, we hope to get that out soon.
nuxt render teleport elements in the beginning of body, not the end like vue. We'll have to wait for this to be fixed for some of the hydration missmatches: https://github.com/nuxt/nuxt/issues/24207
This issue is stale because it has been open for 30 days with no activity. It will not be auto-closed
@xvaara since v3.11.0 nuxt now includes a teleports root element within the body tag.
https://github.com/nuxt/nuxt/releases/tag/v3.11.0
I think the #teleports target ID has to be set by boostrap-vue-next to fix the hydration warnings.
@VividLemon should we default all the teleports to #teleports and maybe add a check to see that it exists and warn about that in dev mode? or could we just create it if missing?
@VividLemon should we default all the teleports to
#teleportsand maybe add a check to see that it exists and warn about that in dev mode? or could we just create it if missing?
Once global options is supported, the nuxt module could just globally set the teleportTo for nuxt specific envionments
The teleportTo solution will probably fix the hydration warnings related to teleports, but there are also lots of other hydration warnings related to element IDs in SSR in the StackBlitz example above. I think #1730 is about those warnings and they could be fixed by #1836. Just wanted to mention that here.
Noticed about ssr:
in nuxt: useId must be used in a component with a single root element, as it uses this root element's attributes to pass the id from server to client.
and we have a lot of components that don't have single root element (teleport isn't a element, so it doesn't work as root here)
if teleport to prop is null or undefined, ssr don't render the content at all. https://github.com/vuejs/core/pull/9783 might fix it?
more missmatch stuff from upstream: nuxt: https://github.com/nuxt/nuxt/issues/27378 vue core: https://github.com/vuejs/core/issues/6638
so if using ssr, set your own id:s for the components
@VividLemon Also noticed that: [nuxt] useId might not work correctly with components that have inheritAttrs: false
so we maybe need to pick the https://github.com/nuxt/nuxt/blob/4d063f1f85cf53f4fa97978f3f8724aacb24174a/packages/nuxt/src/app/composables/id.ts#L5 (data-n-ids) nuxt attrs and put that to the wrapping element for ids to work. At the moment they aren't working in about half of the components.
Then we have a problem with all the other ssr/ssg generator. Haven't tested those at all.
I saw that useId doesn't work with inheritAttrs false, which is a problem considering we can't modify what is properly a fragment component.
So, if data-n-ids is the key to fixing this problem, then I'm all for it.
Technically we could pass through a variable from the nuxt module to check if we are in a nuxt environment and selectively add this attr. Or we could just add it regardless, doesn't really matter.
Then we have a problem with all the other ssr/ssg generator.
Other generators won't get first class support. Nuxt is the most popular by far. If an issue comes that is specific to one framework, those will be dealt on a case by case basis, like we shouldn't just ignore problems, but unless other frameworks have a modules system we can build for, its up to the dev in most cases to fix the issues. (They can implement their own useId function)
There seems to be a lot of fixes in vue 3.5 for ssr! Let's see if it's new useId also fixes our problems. We should maybe use that directly instead of the nuxt one. 3.4.35 has fixes for teleport also, but introduced another bug that bites us: https://github.com/vuejs/core/issues/11230
This seems to have been fixed by Vue 3.5. I checked, not hydration mismatches