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

57,382

Solution 1

Partial answer: with Chrome DevTools, you can localize the issue and see exactly what element caused the issue. Do the following (I did that with Nuxt 5.6.0 and Chrome 64.0.3282.186)

  1. Show DevTools in Chrome (F12)
  2. Load the page that causes "the client-side rendered virtual DOM tree..." warning.
  3. Scroll to the warning in DevTools console.
  4. Click at the source location hyperlink of the warning (in my case it was vue.runtime.esm.js:574).
  5. Set a breakpoint there (left-clicking at line number in the source code browser).
  6. Make the same warning to appear again. I'm not saying it is always possible, but in my case I simply reloaded the page. If there are many warnings, you can check the message by moving a mouse over msg variable.
  7. When you found your message and stopped on a breakpoint, look at the call stack. Click one frame down to call to "patch" to open its source. Hover mouse over hydrate function call 4 lines above the execution line in patch. Hyperlink to the source of hydrate would open.
  8. In the hydrate function, move about 15 lines from the start and set a breakpoint where false is returned after assertNodeMatch returned false. Set the breakpoint there and remove all other breakpoints.
  9. Make the same warning to happen again. Now, when breakpoint is hit, execution should stop in the hydrate function. Switch to DevTools console and evaluate elm and then vnode. Here elm seem to be a server-rendered DOM element while vnode is a virtual DOM node. Elm is printed as HTML so you can figure out where the error happened.

Solution 2

For me this error happened cuz get Array list in AsyncData and rendered <tr> tags by v-for, i put v-for codes in <client-only> blocks and problem solved

Solution 3

This error can be really painfull to debug. In order to quickly get the element causing an issue edit node_modules/vue/dist/vue.esm.js and add the following lines :

// 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)
    // ...


You will get in the console the failing node.

Solution 4

There are a lot of ways of fixing this issue, but most of them are not actual fixes, just hacky band-aids. To note a few:

  • wrap it into <client-only> tags, beware of some important details tho
  • using a v-show instead of a v-if
  • trying to hack some lifecycles
  • etc...

I highly recommend reading this gorgeous article written by Alexander Lichter

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

He'll explain you that you should diagnose why this happens and fix the actual issue.
Basically each time something is different from what was generated on the server and what is available when done hydrating on the client will cause this error.

Some of which are:

  • invalid HTML (having a block element inside of a <p>, same goes for an a tag nested into another, etc...)
  • 3rd party scripts messing around with your components
  • different state on server vs client
  • any random is risky (new Date() for example)
  • any page related to authentication

I highly recommend reading the article to understand in Alexandre's own words how to handle this kind of issue. If you're in a hurry you could always use one band-aid fix but try to actually fix the issue for the best performance and to keep the code clean.

Solution 5

I had the same issue as of nuxt version 2.14.0 while implementing vue-particles package. The fix was to surround the tags with no-ssr and it fixed the issue.

EDIT:
Updated variant of the solution (if Nuxt version is above 2.9.0)

<client-only>
  <vue-particles>
  </vue-particles>
</client-only>

Old solution:

<no-ssr>
  <vue-particles>
  </vue-particles>
</no-ssr>
Share:
57,382
asanas
Author by

asanas

Updated on July 05, 2022

Comments

  • asanas
    asanas almost 2 years

    I am using Nuxt.js / Vuejs for my 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.

  • Tim
    Tim over 5 years
    Nuxt 5.6.0, You live in the future?
  • Michael Giovanni Pumo
    Michael Giovanni Pumo about 5 years
    A quicker way to access the hydrate function execution is to expand the error in the console area of Chrome dev tools and you can see it in the list. Simply click the link after the @ symbol of the same line. e.g. hydrate @ commons.app.js:15934
  • Felix Eve
    Felix Eve almost 4 years
    If your not using Nuxt you will need to install vue-client-only
  • Tekz
    Tekz almost 4 years
    Does this mean we cannot render table server side? and send the complete html to the browser? this really ruin the concept of SSR and SEO features of Nuxt. I get the same issue and can be resolved with <client-only> block but it is not the real fix I guess
  • Alessio
    Alessio over 3 years
    I found that this blog posted an expanded explanation of this error, based on @budden73 answer and it actually helped me understand the problem. Hope this can helps someone else: blog.lichter.io/posts/vue-hydration-error
  • GnxR
    GnxR almost 3 years
    @Tekz you can render tables server-side, as long as you make sure rows are wrapped in <thead>, <tbody> and <tfoot> tags (see MDN for reference on how to use these tags properly)
  • kissu
    kissu almost 3 years
    @FelixEve this one is no longer needed because it is baked into Nuxt.
  • Ashraful Islam Tushar
    Ashraful Islam Tushar almost 2 years
    It is the easiest way to debug this issue. can find out the element responsible for any warning or error. thanks a lot.