-
Notifications
You must be signed in to change notification settings - Fork 29
/
Copy pathserver.js
97 lines (81 loc) · 2.66 KB
/
server.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
const { argv } = require('yargs')
const fs = require('fs')
const express = require('express')
const { createBundleRenderer } = require('vue-server-renderer')
process.chdir(__dirname)
let distDir
if (argv.dev) {
process.env.NODE_ENV = 'development'
distDir = 'tmp'
} else {
process.env.NODE_ENV = 'production'
distDir = 'dist'
}
const configFile = process.env.npm_config_config || argv.config || 'default'
console.log(`loading config ${configFile}`) // eslint-disable-line
const config = require('./config/' + configFile)
const bundle = fs.readFileSync(`${distDir}/server.js`, 'utf8')
const renderer = createBundleRenderer(bundle)
function parseIndexHtml() {
const [
entire,
htmlOpen,
htmlOpenTailAndHead,
headCloseAndBodyOpen,
bodyOpenTailAndContentBeforeApp,
contentAfterAppAndHtmlClose
] = fs.readFileSync(`${distDir}/index.html`, 'utf8').match(/^([\s\S]+?<html)([\s\S]+?)(<\/head>[\s\S]*?<body)([\s\S]+?)<div id="?app"?><\/div>([\s\S]+)$/)
return {
entire,
htmlOpen,
htmlOpenTailAndHead,
headCloseAndBodyOpen,
bodyOpenTailAndContentBeforeApp,
contentAfterAppAndHtmlClose
}
}
const indexHtml = parseIndexHtml()
const app = express()
if (config.serveStaticMountPath) {
app.use(config.serveStaticMountPath, express.static(distDir))
}
app.get('*', (req, res) => {
const context = {
url: req.url
}
renderer.renderToString(context, (err, html) => {
if (err) {
if (err.code === '404') {
// let client to render a 404 page
res.status(404).end(indexHtml.entire)
} else {
// let client to render a 500 page
res.status(500).end(indexHtml.entire)
console.error(`error during render : ${req.url}`) // eslint-disable-line
console.error(err) // eslint-disable-line
}
return
}
const { title, htmlAttrs, bodyAttrs, link, style, script, noscript, meta } = context.meta.inject()
res.write(`
${indexHtml.htmlOpen} data-vue-meta-server-rendered ${htmlAttrs.text()} ${indexHtml.htmlOpenTailAndHead}
${meta.text()}
${title.text()}
${link.text()}
${style.text()}
${script.text()}
${noscript.text()}
${indexHtml.headCloseAndBodyOpen} ${bodyAttrs.text()} ${indexHtml.bodyOpenTailAndContentBeforeApp}
${html}
<script>
window.__INITIAL_COMPONENTS_STATE__ = ${JSON.stringify(context.initialComponentsState)}
window.__INITIAL_VUEX_STATE__ = ${JSON.stringify(context.initialVuexState)}
</script>
${indexHtml.contentAfterAppAndHtmlClose}
`)
res.end()
})
})
app.listen(config.ssrPort, () => {
console.log(`server started at port ${config.ssrPort}`) // eslint-disable-line
})