-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.js
127 lines (106 loc) · 4.13 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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
const express = require('express')
const app = express()
const path = require('path')
const fs = require('fs')
const webpack = require('webpack')
const { createBundleRenderer } = require('vue-server-renderer')
const templatePath = path.resolve(__dirname, './src/template.html')
let template = fs.readFileSync(templatePath, 'utf-8')
const isProd = process.env.NODE_ENV === 'production'
let renderer
let readyPromise
const createRenderer = (serverBundle, clientManifest, template) => {
renderer = createBundleRenderer(serverBundle, {
template,
clientManifest
})
console.log('new renderer created')
}
if (isProd) {
const serverBundle = require('./dist/vue-ssr-server-bundle.json')
const clientManifest = require('./dist/vue-ssr-client-manifest.json')
createRenderer(serverBundle, clientManifest, template)
} else {
// whenever serverBundle, clientManifest or template change, recreate renderer
const clientConfig = require('./webpack.client')()
clientConfig.mode = 'development'
const clientCompiler = webpack(clientConfig)
const devMiddleware = require('webpack-dev-middleware')(clientCompiler, {
publicPath: clientConfig.output.publicPath,
noInfo: true
})
const hotMiddleware = require('webpack-hot-middleware')(clientCompiler)
app.use(devMiddleware)
app.use(hotMiddleware)
const serverConfig = require('./webpack.server')()
const serverCompiler = webpack(serverConfig)
const MFS = require('memory-fs')
readyPromise = createBundles(createRenderer)
function createBundles(createRenderer) {
let clientManifest
let serverBundle
const chokidar = require('chokidar')
// recreate renderer
const update = () => {
if (clientManifest && serverBundle) {
createRenderer(serverBundle, clientManifest, template)
console.log('renderer updated')
}
}
// watch for template file changes
chokidar.watch(templatePath).on('change', () => {
template = fs.readFileSync(templatePath, 'utf-8')
console.log('Template file changed')
update()
})
// watch for client manifest changes
const clientManifestReady = new Promise(resolve => {
clientCompiler.hooks.done.tap('done', (stats) => {
clientManifest = JSON.parse(
devMiddleware.fileSystem.readFileSync(
path.join(clientConfig.output.path, 'vue-ssr-client-manifest.json'),
'utf-8'
)
)
console.log('in client manifest ready')
resolve()
update()
})
})
const serverBundleReady = new Promise(resolve => {
const mfs = new MFS()
serverCompiler.outputFileSystem = mfs
serverCompiler.watch({}, (err, stats) => {
serverBundle = JSON.parse(mfs.readFileSync(path.join(serverConfig.output.path, 'vue-ssr-server-bundle.json'), 'utf-8'))
console.log('in server bundle ready')
resolve()
update()
})
})
return Promise.all([clientManifestReady, serverBundleReady])
.then(() => {
console.log('clientManifest and serverBundle both resolved')
createRenderer(serverBundle, clientManifest, template)
})
}
}
function render(req, res) {
console.log('server hit')
const context = {
url: req.url,
title: 'Creative Group'
}
renderer.renderToString(context)
.then(html => res.end(html))
.catch(err => (
err.statusCode === 404
? res.status(err.statusCode).end('Not found')
: res.status(500).end(`Something went wrong ${err}`))
)
}
app.use('/dist', express.static('dist'))
app.use('/public', express.static('public'))
app.get('*', isProd ? render : (req, res) => {
readyPromise.then(() => render(req, res))
})
app.listen(4000, () => console.log('Server is listening on http://localhost:4000'))