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:
// the default export should be a function // which will receive the context of the render call exportdefaultfunction(context) { returnnewPromise((resolve, reject) => { resolve(app); }); };
Run node ssr-bundle.js comes out a similar html string:
1
<divserver-rendered="true"class="my-app"><h1>Hans-97</h1><h2>age: 20</h2><div><p>Hello Hans-97</p><p>Welcome to China!</p></div></div>
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:
src/client.js
1 2 3 4 5 6 7
import Vue from'vue'; import App from'./App.vue';
const VueApp = Vue.extend(App); new VueApp({ el: '.my-app', });
Then we will improve the above ssr-bundle.js example to an express server:
// Start server const PORT = process.env.PORT || 3000; app.listen(PORT, function () { console.log(`Example app listening on port ${PORT}!`); });
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 http://127.0.0.1:3000/ 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.