Skip to content

Commit 6541a1c

Browse files
committed
feat: reporters and draftlog
1 parent 9d60a17 commit 6541a1c

File tree

15 files changed

+244
-199
lines changed

15 files changed

+244
-199
lines changed

.eslintrc

Lines changed: 0 additions & 3 deletions
This file was deleted.

.eslintrc.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,7 @@ module.exports = {
77
'error',
88
{ singleQuote: true, trailingComma: 'es5', arrowParens: 'always' },
99
],
10+
'class-methods-use-this': 0,
11+
'prefer-template': 0
1012
},
1113
};

kitchen-sync/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22

33
import 'chalk';
44
import 'eslint';
5+
import 'standard-version';

kitchen-sync/webpack.config.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,8 @@ module.exports = {
2121
plugins: [
2222
new Self({
2323
color: 'orange',
24-
profile: true,
24+
// profile: true,
2525
name: 'kitchen-sync',
26-
logStateChanges: true,
2726
}),
2827
],
2928
};

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@
4444
"dependencies": {
4545
"chalk": "^2.4.1",
4646
"consola": "^2.0.0-0",
47+
"draftlog": "^1.0.12",
4748
"figures": "^2.0.0",
48-
"log-update": "^2.3.0",
4949
"pretty-time": "^1.1.0",
5050
"std-env": "^2.0.2",
5151
"text-table": "^0.2.0"

src/index.js

Lines changed: 2 additions & 181 deletions
Original file line numberDiff line numberDiff line change
@@ -1,182 +1,3 @@
1-
import webpack from 'webpack';
2-
import chalk from 'chalk';
3-
import logUpdate from 'log-update';
4-
import env from 'std-env';
5-
import Consola from 'consola';
6-
import prettyTime from 'pretty-time';
1+
import plugin from './plugin';
72

8-
import Profile from './profile';
9-
import { throttle } from './utils';
10-
import { parseRequest, formatRequest } from './utils/request';
11-
import { BULLET } from './utils/consts';
12-
import { renderBar, colorize, ellipsisLeft } from './utils/cli';
13-
14-
const consola = Consola.withTag('webpackbar');
15-
16-
const sharedState = {};
17-
18-
const defaults = {
19-
name: 'webpack',
20-
color: 'green',
21-
profile: false,
22-
compiledIn: true,
23-
done: null,
24-
minimal: env.minimalCLI,
25-
stream: null,
26-
};
27-
28-
const hasRunning = () =>
29-
Object.keys(sharedState)
30-
.map((e) => sharedState[e])
31-
.find((s) => s.isRunning);
32-
33-
const $logUpdate = logUpdate.create(process.stderr, {
34-
showCursor: false,
35-
});
36-
37-
export default class WebpackBarPlugin extends webpack.ProgressPlugin {
38-
constructor(options) {
39-
super();
40-
41-
this.options = Object.assign({}, defaults, options);
42-
43-
// this.handler will be called by webpack.ProgressPlugin
44-
this.handler = (percent, msg, ...details) =>
45-
this.updateProgress(percent, msg, details);
46-
47-
this._render = throttle(this.render.bind(this), 1, 100);
48-
49-
this.logUpdate = this.options.logUpdate || $logUpdate;
50-
51-
if (!this.state) {
52-
sharedState[this.options.name] = {
53-
isRunning: false,
54-
color: this.options.color,
55-
profile: this.options.profile ? new Profile(this.options.name) : null,
56-
};
57-
}
58-
}
59-
60-
get state() {
61-
return sharedState[this.options.name];
62-
}
63-
64-
get stream() {
65-
return this.options.stream || process.stderr;
66-
}
67-
68-
apply(compiler) {
69-
super.apply(compiler);
70-
71-
const hook = (stats) => {
72-
this.state.stats = stats;
73-
if (!hasRunning()) {
74-
this.logUpdate.clear();
75-
this.done();
76-
}
77-
};
78-
79-
if (compiler.hooks) {
80-
compiler.hooks.done.tap('WebpackBar', hook);
81-
} else {
82-
compiler.plugin('done', hook);
83-
}
84-
}
85-
86-
done() {
87-
if (this.options.profile) {
88-
const formattedStats = this.state.profile.getFormattedStats();
89-
this.stream.write(`\n${formattedStats}\n`);
90-
}
91-
92-
if (typeof this.options.done === 'function') {
93-
this.options.done(sharedState, this);
94-
}
95-
}
96-
97-
updateProgress(percent, msg, details = []) {
98-
const progress = Math.floor(percent * 100);
99-
const isRunning = progress < 100;
100-
101-
const wasRunning = this.state.isRunning;
102-
103-
Object.assign(this.state, {
104-
details,
105-
progress,
106-
msg: isRunning && msg ? msg : '',
107-
request: parseRequest(details[2]),
108-
isRunning,
109-
});
110-
111-
if (!wasRunning && isRunning) {
112-
// Started
113-
delete this.state.stats;
114-
this.state.start = process.hrtime();
115-
if (this.options.minimal) {
116-
consola.info(`Compiling ${this.options.name}`);
117-
}
118-
} else if (wasRunning && !isRunning) {
119-
// Finished
120-
const time = process.hrtime(this.state.start);
121-
if (this.options.minimal) {
122-
consola.success(`Compiled ${this.options.name} in ${prettyTime(time)}`);
123-
} else {
124-
this.logUpdate.clear();
125-
if (this.options.compiledIn) {
126-
consola.success(
127-
`${this.options.name} compiled in ${prettyTime(time, 'ms')}`
128-
);
129-
}
130-
}
131-
delete this.state.start;
132-
}
133-
134-
if (this.options.profile) {
135-
this.state.profile.onRequest(this.state.request);
136-
}
137-
138-
this._render();
139-
}
140-
141-
render() {
142-
if (this.options.minimal) {
143-
return;
144-
}
145-
146-
const columns = this.stream.columns || 80;
147-
148-
const stateLines = Object.keys(sharedState)
149-
.sort()
150-
.map((name) => {
151-
const state = sharedState[name];
152-
const color = colorize(state.color);
153-
154-
if (!state.isRunning) {
155-
const color2 = state.progress === 100 ? color : chalk.grey;
156-
return color2(`${BULLET} ${name}\n`);
157-
}
158-
159-
return `${[
160-
color(BULLET),
161-
color(name),
162-
renderBar(state.progress, state.color),
163-
state.msg,
164-
`(${state.progress || 0}%)`,
165-
chalk.grey((state.details && state.details[0]) || ''),
166-
chalk.grey((state.details && state.details[1]) || ''),
167-
].join(' ')}\n ${
168-
state.request
169-
? chalk.grey(
170-
ellipsisLeft(formatRequest(state.request), columns - 2)
171-
)
172-
: ''
173-
}\n`;
174-
});
175-
176-
if (hasRunning()) {
177-
const title = chalk.underline.blue('Compiling');
178-
const log = `\n${title}\n\n${stateLines.join('\n')}`;
179-
this.logUpdate(log);
180-
}
181-
}
182-
}
3+
export default plugin;

src/options.json

Lines changed: 0 additions & 9 deletions
This file was deleted.

src/plugin.js

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import webpack from 'webpack';
2+
import env from 'std-env';
3+
4+
import { LogReporter, BarsReporter, ProfileReporter } from './reporters';
5+
import Profile from './profile';
6+
import { parseRequest } from './utils/request';
7+
8+
// Default plugin options
9+
const DEFAULTS = {
10+
name: 'webpack',
11+
color: 'green',
12+
profile: false,
13+
stream: process.stdout,
14+
reporters: [],
15+
log: !!env.minimalCLI,
16+
bars: !env.minimalCLI,
17+
};
18+
19+
// Mapping from name => { isRunning, details, progress, msg, request }
20+
const globalStates = {};
21+
22+
export default class WebpackBarPlugin extends webpack.ProgressPlugin {
23+
constructor(options) {
24+
super();
25+
26+
this.options = Object.assign({}, DEFAULTS, options);
27+
28+
// this.handler will be called by webpack.ProgressPlugin
29+
this.handler = (percent, msg, ...details) =>
30+
this.updateProgress(percent, msg, details);
31+
32+
// Keep our state in shared ojbect
33+
this.states = globalStates;
34+
if (!this.states[this.options.name]) {
35+
this.states[this.options.name] = {
36+
isRunning: false,
37+
color: this.options.color,
38+
profile: this.options.profile ? new Profile(this.options.name) : null,
39+
status: 'idle',
40+
};
41+
}
42+
this.state = this.states[this.options.name];
43+
44+
// Reporters
45+
this.reporters = Array.from(this.options.reporters || []);
46+
47+
if (this.options.log) {
48+
this.reporters.push(new LogReporter());
49+
}
50+
51+
if (this.options.bars) {
52+
this.reporters.push(new BarsReporter());
53+
}
54+
55+
if (this.options.profile) {
56+
this.reporters.push(new ProfileReporter());
57+
}
58+
}
59+
60+
callReporters(fn, payload = {}) {
61+
for (const reporter of this.reporters) {
62+
if (typeof reporter[fn] === 'function') {
63+
reporter[fn](this, payload);
64+
}
65+
}
66+
}
67+
68+
get hasRunning() {
69+
return Object.keys(this.states)
70+
.map((e) => this.states[e])
71+
.find((s) => s.isRunning);
72+
}
73+
74+
apply(compiler) {
75+
super.apply(compiler);
76+
77+
const hook = (stats) => {
78+
this.state.stats = stats;
79+
if (!this.hasRunning) {
80+
this.callReporters('done');
81+
}
82+
};
83+
84+
if (compiler.hooks) {
85+
compiler.hooks.done.tap('WebpackBar', hook);
86+
} else {
87+
compiler.plugin('done', hook);
88+
}
89+
}
90+
91+
updateProgress(percent, msg, details = []) {
92+
const progress = Math.floor(percent * 100);
93+
const isRunning = progress < 100;
94+
95+
const wasRunning = this.state.isRunning;
96+
97+
Object.assign(this.state, {
98+
details,
99+
progress,
100+
msg: isRunning && msg ? msg : '',
101+
request: parseRequest(details[2]),
102+
elapsed: process.hrtime(this.state.start),
103+
isRunning,
104+
});
105+
106+
if (!wasRunning && isRunning) {
107+
// Started
108+
delete this.state.stats;
109+
this.state.start = process.hrtime();
110+
this.callReporters('compiling');
111+
} else if (wasRunning && !isRunning) {
112+
// Finished
113+
delete this.state.start;
114+
this.callReporters('compiled');
115+
}
116+
117+
if (this.options.profile) {
118+
this.state.profile.onRequest(this.state.request);
119+
}
120+
121+
this.callReporters('update');
122+
}
123+
}

0 commit comments

Comments
 (0)