1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 | const webpack = require('webpack')
|
10 | const getPort = require('get-port')
|
11 | const WebpackDevServer = require('webpack-dev-server')
|
12 | const { TerminalUtils } = require('constellate-dev-utils')
|
13 | const extractError = require('./extract-error')
|
14 | const generateConfig = require('./generate-config')
|
15 |
|
16 | const devInstanceMap = {}
|
17 |
|
18 | const killDevServerFor = pkg => {
|
19 | const devInstance = devInstanceMap[pkg.name]
|
20 | if (!devInstance) {
|
21 | return Promise.resolve()
|
22 | }
|
23 | return new Promise(resolve => {
|
24 | devInstance.webpackDevServer.close(() => {
|
25 | delete devInstanceMap[pkg.name]
|
26 | resolve()
|
27 | })
|
28 | })
|
29 | }
|
30 |
|
31 | module.exports = function develop(
|
32 | pkg ,
|
33 | watcher ,
|
34 | ) {
|
35 | const devInstance = devInstanceMap[pkg.name]
|
36 | if (devInstance) {
|
37 | return Promise.resolve(devInstance.api)
|
38 | }
|
39 |
|
40 | return getPort()
|
41 | .then(port => {
|
42 | TerminalUtils.verbose(`Found free port ${port} for webpack dev server`)
|
43 | return new Promise((resolve, reject) => {
|
44 | let hasResolved = false
|
45 | let showNextSuccess = false
|
46 |
|
47 | const config = generateConfig(pkg, { devServerPort: port })
|
48 | const compiler = webpack(config)
|
49 |
|
50 | const server = new WebpackDevServer(compiler, config.devServer)
|
51 | server.listen(port, '0.0.0.0', () => {
|
52 | TerminalUtils.verbose(
|
53 | `${pkg.name} listening on http://0.0.0.0:${port}`,
|
54 | )
|
55 | })
|
56 |
|
57 | TerminalUtils.info(`Building ${pkg.name}`)
|
58 |
|
59 | compiler.plugin('done', doneStats => {
|
60 | const doneError = extractError(pkg, null, doneStats)
|
61 | if (doneError && hasResolved) {
|
62 | TerminalUtils.error(
|
63 | `Please fix the following issue on ${pkg.name}\n\n${doneError}`,
|
64 | )
|
65 | showNextSuccess = hasResolved && true
|
66 | } else {
|
67 | TerminalUtils[showNextSuccess ? 'success' : 'verbose'](
|
68 | `${pkg.name} is good again`,
|
69 | )
|
70 | showNextSuccess = false
|
71 | }
|
72 | if (!hasResolved) {
|
73 |
|
74 |
|
75 |
|
76 |
|
77 | hasResolved = true
|
78 | if (doneError) {
|
79 | if (server) {
|
80 | try {
|
81 | server.close(() => {
|
82 | reject(doneError)
|
83 | })
|
84 | } catch (err) {
|
85 | TerminalUtils.verbose(
|
86 | 'Could not close existing web-dev-server',
|
87 | )
|
88 | TerminalUtils.verbose(err)
|
89 | reject(doneError)
|
90 | }
|
91 | } else {
|
92 | reject(doneError)
|
93 | }
|
94 | } else {
|
95 | resolve(server)
|
96 | }
|
97 | }
|
98 | })
|
99 | })
|
100 | })
|
101 | .then(webpackDevServer => {
|
102 |
|
103 |
|
104 | watcher.stop()
|
105 | return webpackDevServer
|
106 | })
|
107 | .catch(err => {
|
108 |
|
109 |
|
110 | watcher.start()
|
111 |
|
112 | throw err
|
113 | })
|
114 | .then(webpackDevServer => {
|
115 | const api = {
|
116 | kill: () => killDevServerFor(pkg),
|
117 | }
|
118 | devInstanceMap[pkg.name] = {
|
119 | api,
|
120 | webpackDevServer,
|
121 | }
|
122 | return api
|
123 | })
|
124 | }
|