Open
Description
Vue version
3.5.13
Link to minimal reproduction
https://stackblitz.com/edit/vue-ssr-example-bsqzmafk?file=app.js,client.js,server.js
Steps to reproduce
open your console and see there's a hydration mismatch.
Comp.vue
's useId is not retturning the same value server side and client side
What is expected?
no hydration issue due to useId
What is actually happening?
The cause of this issue is that we run onServerPrefetch
only server-side.
This happen in Nuxt because we treeshake onServerPrefetch
in client-bundle and we also wrap onServerPrefetch
with import.meta.server
flag in useAsyncData
composable.
In runtime, this results into the component being marked as async boudary only server side with markAsyncBoundary
but not client side --> resulting to a hydration issue because useId
returns different strings.
System Info
No response
Any additional comments?
Nuxt issue nuxt/nuxt#30289
Activity
edison1105 commentedon Dec 23, 2024
When rendering on the CSR, it checks if the component contains
onServerPrefetch
hook atcore/packages/runtime-core/src/component.ts
Lines 876 to 879 in 1755ac0
markAsynvBoundary
to make it consistent with SSR behavior.huang-julien commentedon Dec 23, 2024
In Nuxt side, we could either treeshake only the callback of
onServerPrefetch
in client side bundle or addinstance.sp = instance.sp || []
.But i'm not really in favour of the second one tho.
Or maybe can we leave it to vue: we remove the treeshaking of
onServerPrefetch
and maybe can the vue compiler do the treeshaking for client-side bundle ? WDYT ?cc @danielroe
cernymatej commentedon Dec 23, 2024
imho, it would be nice to tree-shake it on the Vue side
danielroe commentedon Dec 23, 2024
I'm happy to remove treeshaking of
onServerPrefetch
, more generally, and leave it up to the vue compiler - but it's not quite that straightforward. In this case, the call toonServerPrefetch
is in an entire separate if/then fork (because data fetching on the server and in the hydration process in the browser run differently).In other words, we'd have to artificially add an 'onServerPrefetch' which awaits an empty promise in order to 'match'. More than happy to do that, but is there another way?
huang-julien commentedon Dec 23, 2024
Yes, useAsyncData is a too specific case to be handled by vue-compiler. In the meantime, we can try the second option using an empty
instance.sp = instance.sp || []
Or fully remove the treeshaking of onServerPrefetch and we try treeshaking the callback in Nuxt side ?
edison1105 commentedon Dec 24, 2024
Vue compiler cannot find all
onServerPrefetch
calls during compilation. Apart from the scenario mentioned by @danielroe, users may also call an externally imported function, which internally callsonServerPrefetch
.