Skip to content

Commit 5151960

Browse files
author
Pooya Parsa
committed
feat: v2 rewrite
BREAKING CHANGE: behaviour and options changed. Refer to the new docs
1 parent 6bd92eb commit 5151960

10 files changed

+133
-152
lines changed

README.md

+11-20
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@
2727

2828
<div align="center">
2929
<br>
30-
<img src="./assets/screen1.jpg" width="600px">
30+
<img src="./assets/screen1.png" width="600px">
3131
<p>Multi progress bars</p>
3232
<br>
3333
</div>
3434

3535
<div align="center">
3636
<br>
37-
<img src="./assets/screen2.jpg" width="90%">
37+
<img src="./assets/screen2.png" width="600px">
3838
<p>Build Profiler</p>
3939
<br>
4040
</div>
@@ -79,13 +79,6 @@ module.exports = {
7979

8080
<h2 align="center">Options</h2>
8181

82-
### `enabled`
83-
84-
By default only enabled when TTY is available and
85-
not running in a [CI](https://github.com/watson/is-ci) environment.
86-
87-
You can force override this option by setting it to `true` or `false`.
88-
8982
### `name`
9083
- Default: `webpack`
9184

@@ -94,36 +87,34 @@ Display name
9487
### `color`
9588
- Default: `green`
9689

97-
Display color (can be hex (`#xxyyzz`) or a web color like `green`)
90+
Display color (can be HEX like `#xxyyzz` or a web color like `green`).
9891

9992
### `profile`
10093
- Default: `false`
10194

102-
Enable profiler
95+
Enable profiler.
10396

10497
### `stream`
105-
- Default: `process.stdout`
98+
- Default: `process.stderr`
10699

107100
Output stream.
108101

109-
### `showCursor`
110-
- Default: `false`
111102

112-
Show the cursor. This can be useful when a CLI accepts input from a user.
103+
### `minimal`
104+
- Default: Auto enabled on CI, non-TTY and test environments
105+
106+
Hide progress bar and only show Compiling/Compiled messages.
113107

114-
### `clear`
108+
### `compiledIn`
115109
- Default: `true`
116110

117-
Auto clear console when compile is finished.
111+
Show `Compiled in ` message after build.
118112

119113
### `done`
120114
- Type: `Function(sharedState, ctx)`
121115

122116
A function that will be called when **all** builds are finished.
123117

124-
### `buildTitle`
125-
- Default: `BUILDING`
126-
127118
<h2 align="center">Maintainers</h2>
128119

129120
<table>

assets/screen1.jpg

-135 KB
Binary file not shown.

assets/screen1.png

46.4 KB
Loading

assets/screen2.jpg

-77.4 KB
Binary file not shown.

assets/screen2.png

148 KB
Loading

kitchen-sync/webpack.config.js

+2-4
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,10 @@ module.exports = {
1919
},
2020
plugins: [
2121
new Self({
22-
color: 'yellow',
23-
showCursor: true,
22+
color: 'orange',
2423
profile: true,
25-
clear: !true,
2624
name: 'webpack-bar',
27-
buildTitle: 'Wait',
25+
logStateChanges: true,
2826
}),
2927
],
3028
};

package.json

+6-6
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@
3535
"dependencies": {
3636
"chalk": "^2.3.2",
3737
"figures": "^2.0.0",
38-
"is-ci": "^1.1.0",
3938
"loader-utils": "^1.1.0",
4039
"lodash": "^4.17.5",
4140
"log-update": "^2.3.0",
4241
"pretty-time": "^1.0.0",
4342
"schema-utils": "^0.4.5",
43+
"std-env": "^1.0.0",
4444
"table": "^4.0.3"
4545
},
4646
"devDependencies": {
@@ -59,20 +59,20 @@
5959
"del-cli": "^1.1.0",
6060
"eslint": "^4.19.1",
6161
"eslint-config-webpack": "^1.2.5",
62-
"eslint-plugin-import": "^2.9.0",
62+
"eslint-plugin-import": "^2.10.0",
6363
"eslint-plugin-prettier": "^2.6.0",
64-
"esm": "^3.0.11",
64+
"esm": "^3.0.14",
6565
"husky": "^0.14.3",
6666
"jest": "^22.4.3",
67-
"lint-staged": "^7.0.0",
67+
"lint-staged": "^7.0.1",
6868
"memory-fs": "^0.4.1",
6969
"nsp": "^3.2.1",
7070
"pre-commit": "^1.2.2",
7171
"prettier": "^1.11.1",
7272
"standard-version": "^4.3.0",
73-
"webpack": "^4.3.0",
73+
"webpack": "^4.4.1",
7474
"webpack-cli": "^2.0.13",
75-
"webpack-defaults": "^2.0.0"
75+
"webpack-defaults": "^2.1.1"
7676
},
7777
"engines": {
7878
"node": ">= 6.9.0 || >= 8.9.0"

src/index.js

+81-96
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ import webpack from 'webpack';
22
import chalk from 'chalk';
33
import _ from 'lodash';
44
import logUpdate from 'log-update';
5-
import isCI from 'is-ci';
5+
import env from 'std-env';
6+
import prettyTime from 'pretty-time';
67
import Profile from './profile';
78
import {
89
BULLET,
10+
TICK,
911
parseRequst,
1012
formatRequest,
1113
renderBar,
@@ -18,74 +20,45 @@ const sharedState = {};
1820
const defaults = {
1921
name: 'webpack',
2022
color: 'green',
21-
stream: process.stdout,
2223
profile: false,
23-
clear: true,
24-
showCursor: false,
25-
enabled: process.stdout.isTTY && !isCI,
24+
compiledIn: true,
2625
done: null,
27-
buildTitle: 'BUILDING',
26+
minimal: env.minimalCLI,
27+
stream: process.stderr,
2828
};
2929

30+
const hasRunning = () => Object.values(sharedState).find((s) => s.isRunning);
31+
3032
export default class WebpackBarPlugin extends webpack.ProgressPlugin {
3133
constructor(options) {
3234
super();
3335

3436
this.options = Object.assign({}, defaults, options);
3537

36-
if (!this.options.enabled) {
37-
return;
38-
}
39-
4038
// this.handler will be called by webpack.ProgressPlugin
4139
this.handler = (percent, msg, ...details) =>
4240
this.updateProgress(percent, msg, details);
4341

4442
this._render = _.throttle(this.render, 25);
4543

46-
this.logUpdate =
47-
this.options.logUpdate ||
48-
logUpdate.create(this.options.stream, {
49-
showCursor: this.options.showCursor,
50-
});
44+
this.logUpdate = this.options.logUpdate || logUpdate;
5145

52-
if (!sharedState[this.options.name]) {
46+
if (!this.state) {
5347
sharedState[this.options.name] = {
48+
isRunning: false,
5449
color: this.options.color,
5550
profile: this.options.profile ? new Profile(this.options.name) : null,
5651
};
5752
}
5853
}
5954

60-
apply(compiler) {
61-
if (!this.options.enabled) {
62-
return;
63-
}
64-
65-
super.apply(compiler);
66-
67-
if (compiler.hooks) {
68-
// Webpack >= 4
69-
compiler.hooks.done.tap('webpackbar', () => this.done());
70-
} else {
71-
// Webpack < 4
72-
compiler.plugin('done', () => this.done());
73-
}
55+
get state() {
56+
return sharedState[this.options.name];
7457
}
7558

7659
done() {
77-
if (!this.options.enabled) {
78-
return;
79-
}
80-
81-
if (Object.values(sharedState).find((s) => s.isRunning)) {
82-
return;
83-
}
84-
85-
this.render();
86-
8760
if (this.options.profile) {
88-
const stats = sharedState[this.options.name].profile.getStats();
61+
const stats = this.state.profile.getStats();
8962
printStats(stats);
9063
}
9164

@@ -95,80 +68,92 @@ export default class WebpackBarPlugin extends webpack.ProgressPlugin {
9568
}
9669

9770
updateProgress(percent, msg, details) {
98-
if (!this.options.enabled) {
99-
return;
100-
}
101-
10271
const progress = Math.floor(percent * 100);
103-
const isRunning = progress && progress !== 100;
72+
const isRunning = progress < 100;
10473

105-
Object.assign(sharedState[this.options.name], {
74+
const wasRunning = this.state.isRunning;
75+
76+
Object.assign(this.state, {
10677
progress,
107-
msg: isRunning ? msg || '' : 'done',
78+
msg: isRunning && msg ? msg : '',
10879
details: details || [],
10980
request: parseRequst(details[2]),
11081
isRunning,
11182
});
11283

84+
if (!wasRunning && isRunning) {
85+
// Started
86+
this.state.start = process.hrtime();
87+
if (this.options.minimal) {
88+
this.stream.write(`Compiling ${this.options.name}\n`);
89+
}
90+
delete this.state.time;
91+
} else if (wasRunning && !isRunning) {
92+
// Finished
93+
const time = process.hrtime(this.state.start);
94+
if (this.options.minimal) {
95+
this.stream.write(
96+
`Compiled ${this.options.name} in ${prettyTime(this.state.time)}\n`
97+
);
98+
} else {
99+
this.logUpdate.clear();
100+
if (this.options.compiledIn) {
101+
process.stdout.write(
102+
`${[
103+
TICK,
104+
this.options.name,
105+
'compiled in',
106+
prettyTime(time, 'ms'),
107+
].join(' ')}\n`
108+
);
109+
}
110+
}
111+
delete this.state.start;
112+
}
113+
113114
if (this.options.profile) {
114-
sharedState[this.options.name].profile.onRequest(
115-
sharedState[this.options.name].request
116-
);
115+
this.state.profile.onRequest(this.state.request);
117116
}
118117

119-
this._render();
118+
if (hasRunning()) {
119+
this._render();
120+
} else {
121+
this.logUpdate.clear();
122+
this.done();
123+
}
120124
}
121125

122126
render() {
123-
const shouldClear = this.options.clear;
124-
let someRunning = false;
125-
126-
const lines = [];
127-
128-
_.sortBy(Object.keys(sharedState), (s) => s.name)
129-
.reverse()
130-
.forEach((name) => {
131-
const state = sharedState[name];
132-
133-
if (state.isRunning) {
134-
someRunning = true;
135-
} else if (shouldClear) {
136-
// Skip done jobs
137-
return;
138-
}
139-
140-
const lColor = colorize(state.color);
141-
const lIcon = lColor(BULLET);
142-
const lName = lColor(_.startCase(name));
143-
const lBar = renderBar(state.progress, state.color);
144-
const lMsg = _.startCase(state.msg);
145-
const lProgress = `(${state.progress || 0}%)`;
146-
const lDetail1 = chalk.grey((state.details && state.details[0]) || '');
147-
const lDetail2 = chalk.grey((state.details && state.details[1]) || '');
148-
const lRequest = state.request ? formatRequest(state.request) : '';
149-
150-
lines.push(
151-
`${[lIcon, lName, lBar, lMsg, lProgress, lDetail1, lDetail2].join(
152-
' '
153-
)}\n ${lRequest}`
154-
);
155-
});
156-
157-
if (shouldClear && !someRunning) {
158-
this.logUpdate.clear();
127+
if (this.options.minimal) {
159128
return;
160129
}
161130

162-
const lLines = lines.join('\n\n');
131+
const stateLines = _.sortBy(Object.keys(sharedState), (n) => n)
132+
.filter((s) => sharedState[s].isRunning || sharedState[s].start)
133+
.map((name) => {
134+
const state = sharedState[name];
135+
const color = colorize(state.color);
163136

164-
if (this.options.buildTitle) {
165-
const title = someRunning
166-
? ` ${chalk.bgBlue.black(` ${this.options.buildTitle} `)}`
167-
: '';
137+
if (!state.isRunning) {
138+
return `${[chalk.grey(BULLET), name].join(' ')}`;
139+
}
168140

169-
this.logUpdate(`\n${title}\n\n${lLines}`);
170-
} else {
171-
this.logUpdate(`\n${lLines}`);
141+
return `${[
142+
color(BULLET),
143+
color(name),
144+
renderBar(state.progress, state.color),
145+
state.msg,
146+
`(${state.progress || 0}%)`,
147+
chalk.grey((state.details && state.details[0]) || ''),
148+
chalk.grey((state.details && state.details[1]) || ''),
149+
].join(' ')}\n ${state.request ? formatRequest(state.request) : ''}\n`;
150+
})
151+
.filter(Boolean);
152+
153+
if (stateLines.length) {
154+
const title = chalk.underline.blue('Compiling');
155+
const log = `\n${title}\n\n${stateLines.join('\n')}`;
156+
this.logUpdate(log);
172157
}
173158
}
174159
}

0 commit comments

Comments
 (0)