UNPKG

3.65 kBJavaScriptView Raw
1//
2
3
4
5
6
7
8
9const webpack = require('webpack')
10const getPort = require('get-port')
11const WebpackDevServer = require('webpack-dev-server')
12const { TerminalUtils } = require('constellate-dev-utils')
13const extractError = require('./extract-error')
14const generateConfig = require('./generate-config')
15
16const devInstanceMap = {}
17
18const 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
31module.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 // This can only be the first time the plugin has run, and therefore
74 // represents the bootstrapping of the web-dev-server. If it failed
75 // then we should kill any running web dev server and reject
76 // the promise to ensure that no dependencies get run.
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 // No need for the watcher now as webpack-dev-server has an inbuilt
103 // watcher.
104 watcher.stop()
105 return webpackDevServer
106 })
107 .catch(err => {
108 // Ensure we fire up the watcher again so that we can track when the
109 // issue is fixed.
110 watcher.start()
111 // Throw the error along
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}