vue hydration text mismatch only in the production build, dev is clean SSR
Nuxt 3.15, Vue 3.5. Dev is completely fine. Deployed build gives me:
Hydration text content mismatch on <div> - rendered on server: 2 hours ago - expected on client: 3 hours ago
and then a chunk of the page re-renders and the scroll position jumps. It's a relative timestamp component. Obviously the server rendered at one time and the client at another, but I don't understand why dev never shows it and what the sanctioned fix is. Wrapping it in <ClientOnly> works but then every card shifts on load.
@tomato_tobin · 7mo ago · 3 replies
Dev never shows it because you're rendering per request against a server clock that's milliseconds from your browser clock. In production the page is cached — CDN, ISR, whatever you have — so the HTML is an hour old by the time a browser sees it. It isn't a Vue bug, your component genuinely isn't deterministic.
The fix that avoids the shift: render the absolute timestamp on the server, upgrade to relative after mount.
Server and client both produce the absolute string for first paint, so hydration matches. Then it swaps. No ClientOnly, and no shift if the element has a stable width.
Reply
Report
@drainfield_dez · 7mo ago
This worked and took ten minutes. The absolute-first render is also better for anyone landing with JS still loading.
Reply
Report
@iris_tanaka · 7mo ago
And better for search — a real
<time datetime>with an absolute value in the HTML beats 'a while ago'.Reply
Report