Client Side Hydration

Hydration refers to the client-side process during which Vue takes over the static HTML sent by the server and turns it into dynamic DOM that can react to client-side data changes.

In entry-client.js, we are simply mounting the app with this line:

// this assumes App.vue template root element has `id="app"`

Since the server has already rendered the markup, we obviously do not want to throw that away and re-create all the DOM elements. Instead, we want to "hydrate" the static markup and make it interactive.

If you inspect the server-rendered output, you will notice that the app's root element has had a special attribute added:

<div id="app" data-server-rendered="true">

The data-server-rendered special attribute lets the client-side Vue know that the markup is rendered by the server and it should mount in hydration mode. Note that it didn't add id="app", just the data-server-rendered attribute: you need to add the ID or some other selector to the app's root element yourself or the app won't hydrate properly.

Note that on elements without the data-server-rendered attribute, hydration can also be forced by passing true to the hydrating argument of $mount:

// Force hydration of the app
app.$mount('#app', true)

In development mode, Vue will assert the client-side generated virtual DOM tree matches the DOM structure rendered from the server. If there is a mismatch, it will bail hydration, discard existing DOM and render from scratch. In production mode, this assertion is disabled for maximum performance.

Hydration Caveats

One thing to be aware of when using SSR + client hydration is some special HTML structures that may be altered by the browser. For example, when you write this in a Vue template:


The browser will automatically inject <tbody> inside <table>, however, the virtual DOM generated by Vue does not contain <tbody>, so it will cause a mismatch. To ensure correct matching, make sure to write valid HTML in your templates.