UNPKG

5.68 kBJavaScriptView Raw
1const chalk = require('chalk')
2const formatWebpackMessages = require('./formatWebpackMessages')
3const clearConsole = require('./clearConsole')
4const { spawn, exec } = require('child_process')
5const path = require('path')
6const { isWindows } = require('./util/platform')
7const psTree = require('pstree.remy')
8
9const isInteractive = process.stdout.isTTY
10
11const createCompiler = (webpack, config, options = {}) => {
12 let compiler
13
14 let app = null
15 let appRunning = false
16 let pid = null
17
18 try {
19 compiler = webpack(config)
20 } catch (err) {
21 console.log(chalk.red('Failed to compile.'))
22 console.log()
23 console.log(err.message || err)
24 console.log()
25 process.exit(1)
26 }
27
28 compiler.hooks.invalid.tap('compileInvalidate', () => {
29 if (isInteractive) {
30 clearConsole()
31 }
32 console.log('Compiling...')
33 if (appRunning && app) {
34 if (isWindows) {
35 exec('taskkill /pid ' + pid + ' /T /F')
36 appRunning = false
37 } else {
38 // pstree is used to kill the full subtree of a spawned app
39 psTree(pid, (_, children) => {
40 if (psTree.hasPS) {
41 // we now send SIGTERM to the spawned process
42 spawn(
43 'kill',
44 ['-s', 'SIGTERM', pid].concat(children)
45 ).on('close', () => {
46 appRunning = false
47 })
48 } else {
49 const pids = children.concat(pid).sort()
50 pids.forEach(pid => {
51 // 15 is for SIGTERM
52 exec('kill -15 ' + pid, () => {
53 /* eslint-disable-line */
54 })
55 })
56 appRunning = false
57 }
58 })
59 }
60 }
61 })
62
63 compiler.hooks.done.tap('compileDone', stats => {
64 if (isInteractive) {
65 clearConsole()
66 }
67
68 const statsJson = stats.toJson({}, true)
69 const messages = formatWebpackMessages(statsJson)
70 const isSuccessful =
71 !messages.errors.length && !messages.warnings.length
72
73 if (isSuccessful) {
74 console.log(
75 `${chalk.green('Compiled successfully!')} ${chalk.dim(
76 `(${statsJson.time}ms)`
77 )}`
78 )
79 console.log()
80 }
81
82 if (messages.errors.length) {
83 const collapsedErrorLength = messages.errors.length - 1
84
85 if (messages.errors.length > 1 && !options.noCollapse) {
86 messages.errors.length = 1
87 }
88
89 console.log(chalk.red('Failed to compile.\n'))
90 console.log(messages.errors.join('\n\n'))
91 if (collapsedErrorLength && !options.noCollapse) {
92 console.log()
93 console.log(
94 chalk.red(
95 collapsedErrorLength +
96 (collapsedErrorLength > 1
97 ? ' errors have'
98 : ' error has') +
99 ' been collapsed.'
100 )
101 )
102 }
103 return
104 }
105
106 // Show warnings if no errors were found.
107 if (messages.warnings.length) {
108 console.log(chalk.yellow('Compiled with warnings.\n'))
109 console.log(messages.warnings.join('\n\n'))
110
111 console.log(
112 '\nSearch for the ' +
113 chalk.cyan('keywords') +
114 ' to learn more about each warning.'
115 )
116 console.log(
117 'To ignore, add ' +
118 chalk.yellow('// tslint:disable-next-line') +
119 ' to the line before.\n'
120 )
121 }
122
123 // Start the app if there are no errors
124 if (!appRunning && !messages.errors.length && !options.noAutoStart) {
125 app = spawn('node', [
126 path.join(config.output.path, config.output.filename),
127 ])
128
129 if (app.pid > 0) {
130 pid = app.pid // eslint-disable-line
131 appRunning = true
132 console.log(chalk.green('App started!'))
133 }
134
135 app.on('error', e => {
136 console.log(chalk.red('Failed to start app: ' + e.message))
137 pid = null
138 app = null
139 appRunning = false
140 })
141
142 app.stdout.pipe(process.stdout)
143 app.stderr.pipe(process.stderr)
144
145 app.on('exit', (code, signal) => {
146 if (code !== null) {
147 console.log(
148 code > 0
149 ? chalk.red('App exited with code ' + code + '.')
150 : chalk.green('App exited with code ' + code + '.')
151 )
152 }
153 if (signal !== null) {
154 console.log(
155 signal !== 'SIGTERM'
156 ? chalk.red(
157 'App killed with signal ' + signal + '.'
158 )
159 : chalk.green('App killed with signal SIGTERM.')
160 )
161 }
162 app = null
163 appRunning = false
164 pid = null
165 })
166 }
167 })
168
169 return compiler
170}
171
172module.exports = {
173 createCompiler,
174}