Vue 2.0 Server-Side Rendering

August 03, 2016 0 Comments vue 2

Vue 2.0 Server-Side Rendering



Vue 2.0 is now in beta6. What I am going to do is checkout how to use SSR (server-side rendering).

Simple Example

Let's make a project first and install some dependencies:

Here is what we get in package.json:

Now we can render a Vue instance to string:

Run node ssr.js comes out the html string:

The root element has a server-rendered="true" attribute. We'll talk about it later.

Bundle Renderer

In most cases, we use numerous .vue files. As we have:

In our server-side entry point, export a function. The function will receive the render context object (passed to bundleRenderer.renderToString or bundleRenderer.renderToStream), and should return a Promise, which should eventually resolve to the app's root Vue instance:

We can easily use webpack + vue-loader with the bundleRenderer.

We do need to use a slightly different webpack.config.js and entry point for our server-side bundle.

And .babelrc is needed:

Run webpack --config webpack/webpack.server.js we'll get a dist/bundle.server.js file as the server-side bundle which can be read in server-side.

Run node ssr-bundle.js comes out a similar html string:

Client Side Hydration

First of all, we have to create another bundle file for client-side. A webpack.client.js is needed. It is almost the same with webpack.server.js except NOT having target: 'node' and output.libraryTarget: 'commonjs2', which bundle the client-side entry file:

Then we will improve the above ssr-bundle.js example to an express server:

For each render call, the code will be re-run in a new context using Node.js' vm module. This ensures your application state is discrete between requests, and you don't need to worry about structuring your application in a limiting pattern just for the sake of SSR.

Now, start the server and hit on your favorite browser. But we get a warning message in the DevTool:

[Vue warn]: The client-side rendered virtual DOM tree is not matching server-rendered content. Bailing hydration and performing full client-side render.

Cause we have the data() function returning a random value in src/App.vue, so we got different html string form server and client via virtual-DOM.

In server-rendered output, the root element will have the server-rendered="true" attribute. On the client, when you mount a Vue instance to an element with this attribute, it will attempt to "hydrate" the existing DOM instead of creating new DOM nodes.

Let's make some change:

Refresh the page and click the +1 button. See what's happening on both server and client side. Checkout this repo to see the full example.

Tag cloud