UNPKG

6.03 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6
7var _webpack = require('webpack');
8
9var _stdEnv = require('std-env');
10
11var _stdEnv2 = _interopRequireDefault(_stdEnv);
12
13var _prettyTime = require('pretty-time');
14
15var _prettyTime2 = _interopRequireDefault(_prettyTime);
16
17var _utils = require('./utils');
18
19var _reporters = require('./reporters');
20
21var reporters = _interopRequireWildcard(_reporters);
22
23var _webpack2 = require('./utils/webpack');
24
25function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
26
27function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
28
29// Default plugin options
30const DEFAULTS = {
31 name: 'webpack',
32 color: 'green',
33 reporters: _stdEnv2.default.minimalCLI ? ['basic'] : ['fancy'],
34 reporter: null
35};
36
37// Default state object
38// eslint-disable-line import/no-namespace
39const DEFAULT_STATE = {
40 start: null,
41 progress: -1,
42 done: false,
43 message: '',
44 details: [],
45 request: null,
46 hasErrors: false
47};
48
49// Mapping from name => State
50const globalStates = {};
51
52class WebpackBarPlugin extends _webpack.ProgressPlugin {
53 constructor(options) {
54 super();
55
56 this.options = Object.assign({}, DEFAULTS, options);
57
58 // Assign a better handler to base ProgressPlugin
59 this.handler = (percent, message, ...details) => {
60 this.updateProgress(percent, message, details);
61 };
62
63 // Reporters
64 this.reporters = Array.from(this.options.reporters || []);
65 if (this.options.reporter) {
66 this.reporters.push(this.options.reporter);
67 }
68
69 // Resolve reposters
70 this.reporters = this.reporters.filter(Boolean).map(_reporter => {
71 if (this.options[_reporter] === false) {
72 return false;
73 }
74
75 let reporter = _reporter;
76 let reporterOptions = this.options[reporter] || {};
77
78 if (Array.isArray(_reporter)) {
79 reporter = _reporter[0]; // eslint-disable-line
80 if (_reporter[1] === false) {
81 return false;
82 }
83 if (_reporter[1]) {
84 reporterOptions = _reporter[1]; // eslint-disable-line
85 }
86 }
87
88 if (typeof reporter === 'string') {
89 if (reporters[reporter]) {
90 reporter = reporters[reporter];
91 } else {
92 reporter = require(reporter); // eslint-disable-line
93 }
94 }
95
96 if (typeof reporter === 'function') {
97 if (typeof reporter.constructor === 'function') {
98 reporter = new reporter(reporterOptions); // eslint-disable-line
99 } else {
100 reporter = reporter(reporterOptions);
101 }
102 }
103
104 return reporter;
105 }).filter(Boolean);
106 }
107
108 callReporters(fn, payload = {}) {
109 for (const reporter of this.reporters) {
110 if (typeof reporter[fn] === 'function') {
111 try {
112 reporter[fn](this, payload);
113 } catch (e) {
114 process.stdout.write(e.stack + '\n');
115 }
116 }
117 }
118 }
119
120 get hasRunning() {
121 return Object.values(this.states).some(state => !state.done);
122 }
123
124 get hasErrors() {
125 return Object.values(this.states).some(state => state.hasErrors);
126 }
127
128 get statesArray() {
129 return Object.values(this.states).sort((s1, s2) => s1.name.localeCompare(s2.name));
130 }
131
132 get states() {
133 return globalStates;
134 }
135
136 get state() {
137 return globalStates[this.options.name];
138 }
139
140 _ensureState() {
141 // Keep our state in shared object
142 if (!this.states[this.options.name]) {
143 this.states[this.options.name] = Object.assign({}, DEFAULT_STATE, {
144 color: this.options.color,
145 name: (0, _utils.startCase)(this.options.name)
146 });
147 }
148 }
149
150 apply(compiler) {
151 // Prevent adding multi instances to the same compiler
152 if (compiler.webpackbar) {
153 return;
154 }
155 compiler.webpackbar = this;
156
157 // Apply base hooks
158 super.apply(compiler);
159
160 // Register our state after all plugins initialized
161 (0, _webpack2.hook)(compiler, 'afterPlugins', () => {
162 this._ensureState();
163 });
164
165 // Hook into the compiler before a new compilation is created.
166 (0, _webpack2.hook)(compiler, 'compile', () => {
167 this._ensureState();
168
169 Object.assign(this.state, Object.assign({}, DEFAULT_STATE, {
170 start: process.hrtime()
171 }));
172
173 this.callReporters('start');
174 });
175
176 // Watch compilation has been invalidated.
177 (0, _webpack2.hook)(compiler, 'invalid', (fileName, changeTime) => {
178 this._ensureState();
179
180 this.callReporters('change', {
181 path: fileName,
182 shortPath: (0, _utils.shortenPath)(fileName),
183 time: changeTime
184 });
185 });
186
187 // Compilation has completed
188 (0, _webpack2.hook)(compiler, 'done', stats => {
189 this._ensureState();
190
191 // Prevent calling done twice
192 if (this.state.done) {
193 return;
194 }
195
196 const hasErrors = stats.hasErrors();
197 const status = hasErrors ? 'with some errors' : 'successfully';
198
199 const time = this.state.start ? ' in ' + (0, _prettyTime2.default)(process.hrtime(this.state.start), 2) : '';
200
201 Object.assign(this.state, Object.assign({}, DEFAULT_STATE, {
202 progress: 100,
203 done: true,
204 message: `Compiled ${status}${time}`,
205 hasErrors
206 }));
207
208 this.callReporters('progress');
209
210 this.callReporters('done', { stats });
211
212 if (!this.hasRunning) {
213 this.callReporters('beforeAllDone');
214 this.callReporters('allDone');
215 this.callReporters('afterAllDone');
216 }
217 });
218 }
219
220 updateProgress(percent = 0, message = '', details = []) {
221 const progress = Math.floor(percent * 100);
222
223 Object.assign(this.state, {
224 progress,
225 message: message || '',
226 details,
227 request: (0, _webpack2.parseRequest)(details[2])
228 });
229
230 this.callReporters('progress');
231 }
232}
233exports.default = WebpackBarPlugin;
\No newline at end of file