-
-
Notifications
You must be signed in to change notification settings - Fork 69
/
Copy pathdev-server.js
146 lines (124 loc) · 4.37 KB
/
dev-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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
const path = require('path')
const MFS = require('memory-fs')
const webpack = require('webpack')
const chalk = require('chalk')
const config = require('./config')
module.exports.setupDevServer = ({ server, templatePath, onUpdate }) => new Promise((resolve, reject) => {
const service = config.service
if (!service) {
reject(new Error('No cli-service available. Make sure you ran the command with `vue-cli-service`.'))
return
}
// Read file in real or virtual file systems
const readFile = (fs, file) => {
try {
return fs.readFileSync(path.join(clientConfigLegacy.output.path, file), 'utf-8')
} catch (e) {}
}
const { getWebpackConfigs } = require('./webpack')
const [clientConfigLegacy, _, serverConfig] = getWebpackConfigs(service)
let serverBundle
let template
let clientManifest
let firstRun = true
let copied = ''
const url = `http://localhost:${config.port}${service.projectOptions.publicPath}`
const update = () => {
if (serverBundle && clientManifest) {
resolve()
onUpdate({
serverBundle,
}, {
template,
clientManifest,
})
}
}
// modify client config to work with hot middleware
clientConfigLegacy.entry.app = ['webpack-hot-middleware/client', ...clientConfigLegacy.entry.app]
clientConfigLegacy.plugins.push(
new webpack.HotModuleReplacementPlugin(),
)
// dev middleware
const clientCompiler = webpack(clientConfigLegacy)
const devMiddleware = require('webpack-dev-middleware')(clientCompiler, {
publicPath: clientConfigLegacy.output.publicPath,
noInfo: true,
stats: 'none',
logLevel: 'error',
index: false,
})
server.use(devMiddleware)
clientCompiler.hooks.done.tap('cli ssr', async stats => {
const jsonStats = stats.toJson()
if (stats.hasErrors()) {
console.log(chalk.red('Client errors'))
jsonStats.errors.forEach(err => console.error(err))
}
if (stats.hasWarnings()) {
console.log(chalk.yellow('Client warnings'))
jsonStats.warnings.forEach(err => console.warn(err))
}
if (stats.hasErrors()) return
// Fix dev server render error when a custom path is used for the server-renderer bundles
const ssrPlugin = (clientConfigLegacy.plugins.find((p) => (p.__pluginName || p.constructor.name) === 'ssr') || {}).options || {}
clientManifest = JSON.parse(readFile(
devMiddleware.fileSystem,
(ssrPlugin && ssrPlugin.filename) || 'vue-ssr-client-manifest.json'
))
// HTML Template
template = devMiddleware.fileSystem.readFileSync(templatePath, 'utf8')
update()
onCompilationCompleted()
})
clientCompiler.hooks.failed.tap('cli ssr', (error) => {
console.log(chalk.red('Client compilation failed'))
console.error(error)
})
// hot module replacement middleware
server.use(require('webpack-hot-middleware')(clientCompiler, { heartbeat: 5000 }))
// watch and update server renderer
const serverCompiler = webpack(serverConfig)
const serverMfs = new MFS()
serverCompiler.outputFileSystem = serverMfs
serverCompiler.watch({}, (err, stats) => {
if (err) {
console.log(chalk.red('Server critical error'))
throw err
}
const jsonStats = stats.toJson()
if (stats.hasErrors()) {
console.log(chalk.red('Server errors'))
jsonStats.errors.forEach(err => console.error(err))
}
if (stats.hasWarnings()) {
console.log(chalk.yellow('Server warnings'))
jsonStats.warnings.forEach(err => console.warn(err))
}
if (stats.hasErrors()) return
// Try to find ssr plugin config options
// to fix dev server render error when a custom path is used for the server-renderer bundles
const ssrPlugin = (serverConfig.plugins.find((p) => (p.__pluginName || p.constructor.name) === 'ssr') || {}).options || {}
// read bundle generated by vue-ssr-webpack-plugin
serverBundle = JSON.parse(readFile(
serverMfs,
(ssrPlugin && ssrPlugin.filename) || 'vue-ssr-server-bundle.json'
))
update()
onCompilationCompleted()
})
function onCompilationCompleted () {
if (firstRun) {
firstRun = false
if (config.copyUrlOnStart) {
require('clipboardy').write(url)
copied = chalk.dim('(copied to clipboard)')
}
}
setTimeout(() => {
console.log()
console.log(' App running at:')
console.log(` - Local: ${chalk.cyan(url)} ${copied}`)
})
}
})