链接

https://github.com/vuejs/core/issues/5991

问题

Hydration children mismatch: server rendered element contains fewer child nodes than client vdom.
Hydration children mismatch: 服务器渲染的元素所包含的子节点比客户端vdom少

相关Pull requests

https://github.com/vuejs/core/pull/5995

相关项目

https://stackblitz.com/edit/github-96ft3e-z7szup
或者

  1. Create a reusable transition with a default slot

    1. <template>
    2. <transition name="custom-transition">
    3. <slot />
    4. </transition>
    5. </template>
  2. Use this transition with v-if inside the slot

    1. <template>
    2. <div>
    3. <CustomTransition>
    4. <div v-if="showData">test</div>
    5. </CustomTransition>
    6. </template>

    SFC Example

    分析

    根据描述来看是和SSR相关的,这个就不能单纯使用SFC来进行调试了,需要在本地build主项目,然后链接到本地项目进行调试。
    如果是一般的非SSR项目,就可以使用

    1. npm run dev-sfc

    进行调试。

    运行项目

    将项目 https://stackblitz.com/edit/github-96ft3e-z7szup 下载到本地,安装依赖,运行项目,看到确实有警告:
    image.png
    额,好像现在支持在SFC里面使用SSR了,这下方便多了!
    SFC SSR Example

    查找原因

    点击进源码,看到是这里在报错
    image.png
    在这个函数开头添加debugger
    image.png
    再次刷新进行单步调试

    找到报错原因

    在这个过程中找到原因:
    SSR过程中的输出和hydrate过程中的vnode对应不上,会有警告。
    image.png
    应该是SSRvnode转成html过程中,把html注释过滤了,具体如何需要去具体项目中debugger看一下。

    1. <div v-if="showData">test</div>

    这个在渲染时应该是一个注释节点
    <!---->
    到了这里,主要是去找在SSR情况下,究竟把模板编译成什么样了,这个可以去SFC ExampleSSR编译结果看一下。
    image.png
    我们看到这个关键函数ssrRenderSlotInner 去源代码中搜索,找到了
    image.png
    刷新页面,代码在断点处此停止
    image.png
    根据单步调试,确实会把注释节点过滤
    image.png
    解决方法就是如何针对这个case进行特殊处理,对

    1. <transition>
    2. <slot />
    3. </transition>

未完待续