Skip to content

Commit

Permalink
feat: reporters and draftlog
Browse files Browse the repository at this point in the history
  • Loading branch information
pi0 committed Nov 1, 2018
1 parent 9d60a17 commit 6541a1c
Show file tree
Hide file tree
Showing 15 changed files with 244 additions and 199 deletions.
3 changes: 0 additions & 3 deletions .eslintrc

This file was deleted.

2 changes: 2 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@ module.exports = {
'error',
{ singleQuote: true, trailingComma: 'es5', arrowParens: 'always' },
],
'class-methods-use-this': 0,
'prefer-template': 0
},
};
1 change: 1 addition & 0 deletions kitchen-sync/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@

import 'chalk';
import 'eslint';
import 'standard-version';
3 changes: 1 addition & 2 deletions kitchen-sync/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,8 @@ module.exports = {
plugins: [
new Self({
color: 'orange',
profile: true,
// profile: true,
name: 'kitchen-sync',
logStateChanges: true,
}),
],
};
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@
"dependencies": {
"chalk": "^2.4.1",
"consola": "^2.0.0-0",
"draftlog": "^1.0.12",
"figures": "^2.0.0",
"log-update": "^2.3.0",
"pretty-time": "^1.1.0",
"std-env": "^2.0.2",
"text-table": "^0.2.0"
Expand Down
183 changes: 2 additions & 181 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,182 +1,3 @@
import webpack from 'webpack';
import chalk from 'chalk';
import logUpdate from 'log-update';
import env from 'std-env';
import Consola from 'consola';
import prettyTime from 'pretty-time';
import plugin from './plugin';

import Profile from './profile';
import { throttle } from './utils';
import { parseRequest, formatRequest } from './utils/request';
import { BULLET } from './utils/consts';
import { renderBar, colorize, ellipsisLeft } from './utils/cli';

const consola = Consola.withTag('webpackbar');

const sharedState = {};

const defaults = {
name: 'webpack',
color: 'green',
profile: false,
compiledIn: true,
done: null,
minimal: env.minimalCLI,
stream: null,
};

const hasRunning = () =>
Object.keys(sharedState)
.map((e) => sharedState[e])
.find((s) => s.isRunning);

const $logUpdate = logUpdate.create(process.stderr, {
showCursor: false,
});

export default class WebpackBarPlugin extends webpack.ProgressPlugin {
constructor(options) {
super();

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

// this.handler will be called by webpack.ProgressPlugin
this.handler = (percent, msg, ...details) =>
this.updateProgress(percent, msg, details);

this._render = throttle(this.render.bind(this), 1, 100);

this.logUpdate = this.options.logUpdate || $logUpdate;

if (!this.state) {
sharedState[this.options.name] = {
isRunning: false,
color: this.options.color,
profile: this.options.profile ? new Profile(this.options.name) : null,
};
}
}

get state() {
return sharedState[this.options.name];
}

get stream() {
return this.options.stream || process.stderr;
}

apply(compiler) {
super.apply(compiler);

const hook = (stats) => {
this.state.stats = stats;
if (!hasRunning()) {
this.logUpdate.clear();
this.done();
}
};

if (compiler.hooks) {
compiler.hooks.done.tap('WebpackBar', hook);
} else {
compiler.plugin('done', hook);
}
}

done() {
if (this.options.profile) {
const formattedStats = this.state.profile.getFormattedStats();
this.stream.write(`\n${formattedStats}\n`);
}

if (typeof this.options.done === 'function') {
this.options.done(sharedState, this);
}
}

updateProgress(percent, msg, details = []) {
const progress = Math.floor(percent * 100);
const isRunning = progress < 100;

const wasRunning = this.state.isRunning;

Object.assign(this.state, {
details,
progress,
msg: isRunning && msg ? msg : '',
request: parseRequest(details[2]),
isRunning,
});

if (!wasRunning && isRunning) {
// Started
delete this.state.stats;
this.state.start = process.hrtime();
if (this.options.minimal) {
consola.info(`Compiling ${this.options.name}`);
}
} else if (wasRunning && !isRunning) {
// Finished
const time = process.hrtime(this.state.start);
if (this.options.minimal) {
consola.success(`Compiled ${this.options.name} in ${prettyTime(time)}`);
} else {
this.logUpdate.clear();
if (this.options.compiledIn) {
consola.success(
`${this.options.name} compiled in ${prettyTime(time, 'ms')}`
);
}
}
delete this.state.start;
}

if (this.options.profile) {
this.state.profile.onRequest(this.state.request);
}

this._render();
}

render() {
if (this.options.minimal) {
return;
}

const columns = this.stream.columns || 80;

const stateLines = Object.keys(sharedState)
.sort()
.map((name) => {
const state = sharedState[name];
const color = colorize(state.color);

if (!state.isRunning) {
const color2 = state.progress === 100 ? color : chalk.grey;
return color2(`${BULLET} ${name}\n`);
}

return `${[
color(BULLET),
color(name),
renderBar(state.progress, state.color),
state.msg,
`(${state.progress || 0}%)`,
chalk.grey((state.details && state.details[0]) || ''),
chalk.grey((state.details && state.details[1]) || ''),
].join(' ')}\n ${
state.request
? chalk.grey(
ellipsisLeft(formatRequest(state.request), columns - 2)
)
: ''
}\n`;
});

if (hasRunning()) {
const title = chalk.underline.blue('Compiling');
const log = `\n${title}\n\n${stateLines.join('\n')}`;
this.logUpdate(log);
}
}
}
export default plugin;
9 changes: 0 additions & 9 deletions src/options.json

This file was deleted.

123 changes: 123 additions & 0 deletions src/plugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import webpack from 'webpack';
import env from 'std-env';

import { LogReporter, BarsReporter, ProfileReporter } from './reporters';
import Profile from './profile';
import { parseRequest } from './utils/request';

// Default plugin options
const DEFAULTS = {
name: 'webpack',
color: 'green',
profile: false,
stream: process.stdout,
reporters: [],
log: !!env.minimalCLI,
bars: !env.minimalCLI,
};

// Mapping from name => { isRunning, details, progress, msg, request }
const globalStates = {};

export default class WebpackBarPlugin extends webpack.ProgressPlugin {
constructor(options) {
super();

this.options = Object.assign({}, DEFAULTS, options);

// this.handler will be called by webpack.ProgressPlugin
this.handler = (percent, msg, ...details) =>
this.updateProgress(percent, msg, details);

// Keep our state in shared ojbect
this.states = globalStates;
if (!this.states[this.options.name]) {
this.states[this.options.name] = {
isRunning: false,
color: this.options.color,
profile: this.options.profile ? new Profile(this.options.name) : null,
status: 'idle',
};
}
this.state = this.states[this.options.name];

// Reporters
this.reporters = Array.from(this.options.reporters || []);

if (this.options.log) {
this.reporters.push(new LogReporter());
}

if (this.options.bars) {
this.reporters.push(new BarsReporter());
}

if (this.options.profile) {
this.reporters.push(new ProfileReporter());
}
}

callReporters(fn, payload = {}) {
for (const reporter of this.reporters) {
if (typeof reporter[fn] === 'function') {
reporter[fn](this, payload);
}
}
}

get hasRunning() {
return Object.keys(this.states)
.map((e) => this.states[e])
.find((s) => s.isRunning);
}

apply(compiler) {
super.apply(compiler);

const hook = (stats) => {
this.state.stats = stats;
if (!this.hasRunning) {
this.callReporters('done');
}
};

if (compiler.hooks) {
compiler.hooks.done.tap('WebpackBar', hook);
} else {
compiler.plugin('done', hook);
}
}

updateProgress(percent, msg, details = []) {
const progress = Math.floor(percent * 100);
const isRunning = progress < 100;

const wasRunning = this.state.isRunning;

Object.assign(this.state, {
details,
progress,
msg: isRunning && msg ? msg : '',
request: parseRequest(details[2]),
elapsed: process.hrtime(this.state.start),
isRunning,
});

if (!wasRunning && isRunning) {
// Started
delete this.state.stats;
this.state.start = process.hrtime();
this.callReporters('compiling');
} else if (wasRunning && !isRunning) {
// Finished
delete this.state.start;
this.callReporters('compiled');
}

if (this.options.profile) {
this.state.profile.onRequest(this.state.request);
}

this.callReporters('update');
}
}
Loading

0 comments on commit 6541a1c

Please sign in to comment.