Vue SSR Tools
Tooling for working with Vue server side
Table of Contents
Preparations
If you do not have a project already, create a new folder and initialize it:
mkdir my-cool-project
npm init
After you're done answerin the npm questions, edit your new package.json
file and add a new line containing: type="module"
.
Dependencies
Some packages or some compatible equivalent needs to be installed:
npm i vue vue-router vue-server-renderer express
Node with ESM Module support needed. Node 8 and up supports this under the flag --experimental-modules
and from Node 13.2 ESM Modules should be supported without the flag (as I write this Node 13.1 is the latest release).
Installation
npm i vue-ssr-tools
Usage
1. Basic server side render with router
This is the most basic implementation without client side hydration (Vue only runs server side)
index.js
;;;;; // The router must be attached to the vue before anything else happends// this is ugly as **** and will most likely be removed in Vue 3Vue; const server = ; // Instance of a SSR vue render thingie with routes and allconst vueRender = // Router constructor, must be compatible with vue-router // but you can hack your own if you like Router // The base template all pages will share. // {{ title }} and {{{ head }}} will be covered later // <!-- vue-ssr-outlet --> will be replaced with // your main component (see above) template: `<!DOCTYPE html> <html lang="en"> <head> <title>{{ title }}</title> <meta charset="utf-8" /> {{{ head }}} </head> <body> <!--vue-ssr-outlet--> </body> </html>` // Vue constructor Vue // Vue server side renderer vueServerRenderer; // Instantiate main component and routes for each request,// since they might need request specific data.// They are also async since when they get more complex in the// future might need to resolve data and other async stuff// before they are ready// Then run the vue render minddlewareserver; server;
test it out by running it from the console: node index.js
(or for node 8-12: node --experimental-modules index.js
)
2. Client side hydration
Make vue work on the client as well
2.1. Break apart the code we want to use both client- and serverside
In this step, we make no change to the actual code, just splitting it up in different files.
The main vue component is the vue component that will be mounted in the html template.
public/vue/components/main.js
{ return template: `<div id="vue-main"> <ul> <li><router-link to="/">Home</router-link></li> <li><router-link to="/foo">Foo</router-link></li> </ul> <router-view></router-view> </div>` ;}
Routes sent to the router, see vue-router documentation for more options and how these actually work.
public/vue/routes.js
{ return path: '/' component: template: '<p>Home</p>' path: '/foo' component: template: '<p>Foo</p>' ;}
The base template all pages will share. {{ title }} and {{{ head }}} will be covered later. <!-- vue-ssr-outlet -->
will be replaced with
your main component (see above).
index.template.html
{{ title }} {{{ head }}} <!--vue-ssr-outlet-->
Tie it all together in the index file.
index.js
;;;;; // Imported stuff not needed when all was in the same file:;;; Vue; const server = ; // Instance of a SSR vue render thingie with routes and allconst vueRender = Router template: fs Vue vueServerRenderer; // Instantiate main component and routes for each request// and register the vueRender middleware on the express serverserver; server;
2.2. Create new files needed client side
First we need to modify our index to serve our node_modules and public folders to the browser.
index.js
;;;;; // Imported stuff not needed when all was in the same file:;;; Vue; const server = ; // Serve the public folder as static files directlyserver; // Server node modules publiclyserver; // Instance of a SSR vue render thingie with routes and allconst vueRender = Router template: fs Vue vueServerRenderer; // Instantiate main component and routes for each request// and register the vueRender middleware on the express serverserver; server;
This file is only ran client side to create the vue app in the browser.
public/vue/entry.js
;;;;; Vue; async { const app = await ; app};
We also need to modify our base template to include our client entry file.
index.template.html
{{ title }} {{{ head }}} <!--vue-ssr-outlet-->
3. Write component templates in separate HTML file
In this section we use a handy tool to write the vue component template part in a HTML file for better editor support and maintainability.
First we load a little tool that fetches html-files for us, we do this in index.js and public/vue/entry.js
index.js
;;;;; // Imported stuff not needed when all was in the same file:;;; Vue; const server = ;const getVueTmpl = publicHost: 'http://localhost:3000' templatesBasePath: '/vue/templates/'; // Serve the public folder as static files directlyserver; // Server node modules publiclyserver; // Instance of a SSR vue render thingie with routes and allconst vueRender = Router template: fs Vue vueServerRenderer; // Instantiate main component and routes for each request// and register the vueRender middleware on the express serverserver; server;
public/vue/components/main.js
{ const getVueTmpl = options; return template: await getVueTmpl ;}
public/vue/templates/main.html
<div id="vue-main"> <ul> <li><router-link to="/">Home</router-link></li> <li><router-link to="/foo">Foo</router-link></li> </ul> <router-view></router-view></div>
public/vue/entry.js
;;;;; Vue; const getVueTmpl = publicHost: 'http://localhost:3000' templatesBasePath: '/vue/templates/'; async { const app = await ; app};