Subscribe on changes!

encounter " Hydration node mismatch" when using keep-alive in ssr rendering

avatar
Oct 19th 2021

Version

3.2.20

Reproduction link

github.com

Steps to reproduce

first, change the App.vue file to the following( replace <Suspense> with <keep-alive>)

<template>
  <div>
    <router-link to="/">Home</router-link>|
    <router-link to="/about">About</router-link>
    <router-view v-slot="{ Component }">
      <keep-alive>
        <component :is="Component" />
      </keep-alive>
    </router-view>
  </div>
</template>

second, run pnpm run dev third, access http://localhost:3000/

and you will see the error in console panel.

What is expected?

no error is reported

What is actually happening?

there is a error


even though the reproduction project is using vite, the error is still there when you using webpack.

avatar
Oct 19th 2021

there is a screenshot image

avatar
Nov 16th 2021

I'm having the same problem, using Quasar framework. The component rendered by <router-view> server side is wrapped in a <!--[--> <!--]--> that the client is not expecting.

avatar
Nov 17th 2021

same problem.

avatar
Nov 21st 2021

I am also noticing something similar also happen with the fragment comments

- Client vnode: div 
- Server rendered DOM: <!--[--> (start of fragment)

Nothing actually seems to be mismatched besides these comments. From what I can tell they are used for v-for and , possibly also for components with more than 1 root element.

avatar
Dec 7th 2021

Same problem here. Seems to appear on v-for and dynamic components <component :is="" />

@tcstory Could you find a solution?

avatar
Feb 8th 2022

Was anyone able to find a solution for this? Have the same problem using Quasar 2.5.4 @tcstory

avatar
Mar 28th 2022

It seems that the server-side rendering code https://github.com/vuejs/core/blob/1070f127a78bfe7da6fe550cc272ef11a1f434a0/packages/runtime-core/src/components/KeepAlive.ts#L98-L101 does not match the client-side rendering logic and it should be rewritten like this:

  if (!sharedContext.renderer) {
    return () => {
      if (!slots.default) {
        return null;
      }

      const children = slots.default();
      if (children.length > 1) {
        warn(`KeepAlive should contain exactly one component child.`);
        return children;
      }

      return children[0];
  }
}