Use Vue 2.0 server-side rendering with Express
npm i vue-ssr --save
const express = require('express')
const router = express.Router()
const VueSSR = require('vue-ssr')
// webpack server-side bundle config
const serverConfig = require('path to webpack.server.js')
// create a project renderer
const indexRenderer = new VueSSR({
projectName: 'index',
rendererOptions: {
cache: require('lru-cache')({
max: 1000,
maxAge: 1000 * 60 * 15
})
},
webpackServer: serverConfig
})
// handle
function indexView (req, res) => {
indexRenderer.render(req, res, `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Cov-X</title>
{{ STYLE }}
</head>
<body>
{{ APP }}
<script src="/dist/client-bundle.js"></script>
</body>
</html>
`)
}
router.get('/', indexView)
router.get('/home', indexView)
router.get('/article', indexView)
router.get('/tag', indexView)
project name of webpack entries that you want to server side rendering
// webpack config
...
entry: {
index: ['../path to app client entry'],
dashboard: ['../path to dashboard project client entry']
},
...
const indexRenderer = new VueSSR({
projectName: 'index',
webpackServer: serverConfig
})
const dashRenderer = new VueSSR({
projectName: 'dashboard',
webpackServer: serverConfig
})
rendererOptions is Vue server renderer options
Allows you to provide server-side implementations for your custom directives:
const indexRenderer = new VueSSR('index', {
directives: {
example (vnode, directiveMeta) {
// transform vnode based on directive binding metadata
}
}
}, serverConfig)
const indexRenderer = new VueSSR('index', {
cache: require('lru-cache')({
max: 1000,
maxAge: 1000 * 60 * 15
})
}, serverConfig)
for example webpack.server.js
const serverConfig = require('path to webpack.server.js')
const indexRenderer = new VueSSR({
projectName: 'index',
webpackServer: serverConfig
})
The default AppHtml is {{ APP }}
, rendering of the server side is replaced by AppHtml
<html>
<body>
{{ APP }}
</body>
</html>
<html>
<body>
<div id="app" server-rendered="true">
...
</div>
</body>
</html>
You can also customize it
const indexRenderer = new VueSSR({
projectName: 'index',
webpackServer: serverConfig,
AppHtml: '<div id="app"></div>'
})
const indexRenderer = new VueSSR({
contextHandler: function (req) {
return {
url: req.url,
ua: uaParser(req.headers['user-agent'])
}
}
})
const indexRenderer = new VueSSR({
defaultHeadData: {
baseTitle: 'VueSSR',
baseKeywords: ',vue-ssr',
baseDescription: 'Vue server-side rendering',
title: '',
description: '',
keywords: ''
}
})
head
meta(charset="utf-8")
meta(name="renderer", content="webkit")
title {{ _VueSSR_Title }}
meta(name="viewport", content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no")
meta(name="keywords", content="{{ _VueSSR_Keywords }}")
meta(name="description", content="{{ _VueSSR_Description }}")
server-entry.js
export default context => {
router.push(context.url)
return Promise.all(router.getMatchedComponents().map(component => {
if (component.preFetch) {
return component.preFetch(store, router, context)
}
})).then(() => {
context.initialState = store.state
return app
})
}
simple component
export default {
preFetch (store, router, context) {
context.headData = {
title: 'this article's title,
description: 'about this article',
keywords: 'Vue,vuejs,javascript'
}
return Promise.resolve()
}
}
MIT