Vuejs Error: The client-side rendered virtual DOM tree is not matching server-rendered

时间:2017-12-18 05:29:46

标签: javascript vue.js vuejs2 nuxt.js

I am using Nuxt.js / Vuejs for mmy app, and I keep facing this error in different places:

    The client-side rendered virtual DOM tree is not matching server-rendered content. 
This is likely caused by incorrect HTML markup, for example nesting block-level elements inside <p>, or missing <tbody>. 
Bailing hydration and performing full client-side render.

I would like to understand what is the best way to debug this error? Is their a way I can record/get the virtual DOM tree for client and server so I could compare and find where the error lies?

Mine is a large application and manually verifying is difficult.

15 个答案:

答案 0 :(得分:28)

部分答案:使用Chrome DevTools,您可以本地化问题并确切了解导致问题的元素。执行以下操作(我使用Nuxt 5.6.0和Chrome 64.0.3282.186执行此操作)

  1. 在Chrome中显示DevTools(F12)
  2. 加载导致&#34;客户端呈现的虚拟DOM树的页面...&#34;警告。
  3. 滚动到DevTools控制台中的警告。
  4. 单击警告的源位置超链接(在我的情况下,它是vue.runtime.esm.js:574)。
  5. 在那里设置断点(在源代码浏览器中左键单击行号)。
  6. 再次出现相同的警告。我并不是说它总是可行的,但就我而言,我只是重新加载页面。如果有许多警告,您可以通过将鼠标移到msg变量上来检查消息。
  7. 当您找到消息并在断点处停止时,请查看调用堆栈。单击一帧向下呼叫&#34; patch&#34;打开它的来源。将鼠标悬停在hydrate函数上,调用patch中执行行上方的4行。将打开hydrate来源的超链接。
  8. hydrate函数中,从一开始就移动大约15行,并设置一个断点,false返回assertNodeMatch后返回false。在那里设置断点并删除所有其他断点。
  9. 再次发出相同的警告。现在,当遇到断点时,执行应该在hydrate函数中停止。切换到DevTools控制台并评估elm,然后评估vnode。这里elm似乎是一个服务器呈现的DOM元素,而vnode是一个虚拟DOM节点。 Elm以HTML格式打印,因此您可以找出错误发生的位置。

答案 1 :(得分:11)

对我来说,发生此错误是因为cuz在AsyncData中获取数组列表,并由<tr>渲染了v-for标签,我在v-for块中放置了<client-only>代码,并出现了问题解决了

答案 2 :(得分:4)

在实现vue-particles软件包时,我遇到了与nuxt 2.14.0版相同的问题。 解决方法是围绕标签no-ssr并解决了该问题。 例子:

<no-ssr>
    <vue-particles>
    </vue-particles>
</no-ssr>

答案 3 :(得分:3)

对于高于2.10的Nuxt版本,它不需要安装任何东西,只需使用默认的组件<client-only>,如https://nuxtjs.org/api/components-client-only/所述。

答案 4 :(得分:2)

此错误真的很难调试。为了快速获取引起问题的元素,请编辑node_modules/vue/dist/vue.esm.js并添加以下几行:

// Search for this line: 
function hydrate (elm, vnode, insertedVnodeQueue, inVPre) {
    var i;
    var tag = vnode.tag;
    var data = vnode.data;
    var children = vnode.children;
    inVPre = inVPre || (data && data.pre);
    vnode.elm = elm;

    // Add the following lines: 
    console.log('elm', elm)
    console.log('vnode', vnode)
    console.log('inVpre', inVPre)
    // ...


您将在控制台中找到发生故障的节点。

答案 5 :(得分:2)

如果您使用 v-if 有条件地渲染组件,那么您有两种选择来解决该问题:

第一个是将元素包裹在 <no-ssr></no-ssr> 标签中。

第二种方法是用 v-if 替换 v-showhere 是 Vue 文档的链接。

答案 6 :(得分:1)

结果,就我而言,我有HTML注释标签,这引起了这个愚蠢,令人讨厌的错误。花了我很长时间才弄清楚它,但万一它对某人有帮助。

答案 7 :(得分:1)

就我而言,我必须更改此设置:

<v-expansion-panel-header v-text="name" />

对此:

<v-expansion-panel-header>{{ name }}</v-expansion-panel-header>

答案 8 :(得分:1)

有很多方法可以解决这个问题,但其中大部分都不是真正的修复,只是临时用的创可贴。注意几点:

  • 将其包装成 <client-only> 标签
  • 使用 v-show 而不是 v-if
  • 试图破解一些生命周期
  • 等等...

我强烈推荐阅读亚历山大·利希特 (Alexander Lichter) 撰写的这篇精彩的文章

<块引用>

https://blog.lichter.io/posts/vue-hydration-error/

他会向您解释,您应该诊断为什么会发生这种情况并解决实际问题。
基本上每次与在服务器上生成的内容以及在客户端上完成补水后可用的内容不同时,都会导致此错误。

其中一些是:

  • 无效的 HTML(在 <p> 中包含块元素是无效的)
  • 第 3 方脚本干扰了您的组件
  • 服务器与客户端的不同状态
  • 任何随机都是有风险的(例如new Date()
  • 任何与身份验证相关的页面

我强烈建议您阅读这篇文章,用 Alexandre 自己的话了解如何处理此类问题。如果您赶时间,您可以随时使用创可贴修复,但尝试实际修复问题以获得最佳性能并保持代码清洁。

答案 9 :(得分:0)

请参阅此处,以获取有关如何处理修改DOM的集成(例如Google Analytics(分析)或FB Pixel)的示例。基本上创建一个插件,并从SSR中排除。

https://nuxtjs.org/faq/google-analytics/

答案 10 :(得分:0)

好吧,这听起来很愚蠢。我尝试了大约15分钟的各种解决方案,例如重新启动服务器和删除.nuxt目录,但是我懒得使用@ budden73的大脑力解决方案。最终对我有用的只是重新启动计算机,试一试。

答案 11 :(得分:0)

到目前为止,我发现还没有发现,当您使用jQuery之类的第三方程序包时(特别是),它们有时会在dom中注入html标签。因此,Vue / Nuxt松开了dom树的记录并开始抱怨。

我遇到了同样的问题,过了一会儿,我删除了所有jQuery,并用Vuejs替换了jQuery功能,这些错误都消失了。

答案 12 :(得分:0)

检查先前的警告:

"nuxt": "^2.12.2"中,您可以从先前的警告中轻松找出原因。

enter image description here

在我的情况下:

不正确

                <nuxt-link to="/game42day">
                    <a>Game For Today</a>
                </nuxt-link>

正确:

                <nuxt-link to="/game42day">
                    Game For Today
                </nuxt-link>

答案 13 :(得分:0)

答案 14 :(得分:0)

检查是否在内联元素中使用了任何块级元素。

例如:里面,里面

如果您使用过 HTML 表格,请确保您使用了标签