1 | const chalk = require('chalk')
|
2 | const formatWebpackMessages = require('./formatWebpackMessages')
|
3 | const clearConsole = require('./clearConsole')
|
4 | const { spawn, exec } = require('child_process')
|
5 | const path = require('path')
|
6 | const { isWindows } = require('./util/platform')
|
7 | const psTree = require('pstree.remy')
|
8 |
|
9 | const isInteractive = process.stdout.isTTY
|
10 |
|
11 | const 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 |
|
39 | psTree(pid, (_, children) => {
|
40 | if (psTree.hasPS) {
|
41 |
|
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 |
|
52 | exec('kill -15 ' + pid, () => {
|
53 |
|
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 |
|
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 |
|
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
|
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 |
|
172 | module.exports = {
|
173 | createCompiler,
|
174 | }
|