diff --git a/README.md b/README.md
index 10e3381..69e9893 100644
--- a/README.md
+++ b/README.md
@@ -93,20 +93,23 @@ SpeedMeasurePlugin.wrapPlugins(pluginMap, options);
### `options.outputFormat`
-Type: `String`
+Type: `String|Function`
Default: `"human"`
Determines in what format this plugin prints its measurements
* `"json"` - produces a JSON blob
* `"human"` - produces a human readable output
+ * `"humanVerbose"` - produces a more verbose version of the human readable output
+ * If a function, it will call the function with the JSON blob being the first parameter, and just the response of the function as the output
### `options.outputTarget`
-Type: `String`
-Default: `undefined`
+Type: `String|Function`
+Default: `console.log`
-Specifies the path to a file to output to. If undefined, then output will print to `console.log`
+* If a string, it specifies the path to a file to output to.
+* If a function, it will call the function with the output as the first parameter
### `options.disable`
diff --git a/colours.js b/colours.js
index a1e9b93..ab2bac8 100644
--- a/colours.js
+++ b/colours.js
@@ -1,16 +1,19 @@
-const green = "\x1b[32m";
-const yellow = "\x1b[33m";
-const red = "\x1b[31m";
+const greenFg = "\x1b[32m";
+const yellowFg = "\x1b[33m";
+const redFg = "\x1b[31m";
+const blackBg = "\x1b[40m";
const bold = "\x1b[1m";
const end = "\x1b[0m";
-module.exports.b = (text, time) => {
+module.exports.fg = (text, time) => {
let colour;
- if (time >= 0) colour = green;
- if (time > 2000) colour = yellow;
- if (time > 10000) colour = red;
+ if (time >= 0) colour = greenFg;
+ if (time > 2000) colour = yellowFg;
+ if (time > 10000) colour = redFg;
return (colour || "") + bold + text + end;
};
+module.exports.bg = text => blackBg + greenFg + bold + text + end;
+
module.exports.stripColours = text => text.replace(/\x1b\[[0-9]+m/g, "");
diff --git a/index.js b/index.js
index dcd49bd..3d6c266 100644
--- a/index.js
+++ b/index.js
@@ -55,9 +55,13 @@ module.exports = class SpeedMeasurePlugin {
if (this.timeEventData.loaders)
outputObj.loaders = getLoadersOutput(this.timeEventData.loaders);
- return this.options.outputFormat === "json"
- ? JSON.stringify(outputObj, null, 2)
- : getHumanOutput(outputObj);
+ if (this.options.outputFormat === "json")
+ return JSON.stringify(outputObj, null, 2);
+ if (typeof this.options.outputFormat === "function")
+ return this.options.outputFormat(outputObj);
+ return getHumanOutput(outputObj, {
+ verbose: this.options.outputFormat === "humanVerbose",
+ });
}
addTimeEvent(category, event, eventType, data = {}) {
@@ -99,7 +103,7 @@ module.exports = class SpeedMeasurePlugin {
this.addTimeEvent("misc", "compile", "end");
const output = this.getOutput();
- if (this.options.outputTarget) {
+ if (typeof this.options.outputTarget === "string") {
const strippedOutput = stripColours(output);
const writeMethod = fs.existsSync(this.options.outputTarget)
? fs.appendFile
@@ -109,7 +113,8 @@ module.exports = class SpeedMeasurePlugin {
console.log("Outputted timing info to " + this.options.outputTarget);
});
} else {
- console.log(output);
+ const outputFunc = this.options.outputTarget || console.log;
+ outputFunc(output);
}
this.timeEventData = {};
diff --git a/output.js b/output.js
index 3fa578b..4dfcd6c 100644
--- a/output.js
+++ b/output.js
@@ -1,67 +1,94 @@
-const { b } = require("./colours");
+const MS_IN_MINUTE = 60000;
+const MS_IN_SECOND = 1000;
+
+const { fg, bg } = require("./colours");
const { groupBy, getAverages, getTotalActiveTime } = require("./utils");
-const humanTime = ms => {
- const hours = ms / 3600000;
- const minutes = ms / 60000;
- const seconds = ms / 1000;
+const humanTime = (ms, options = {}) => {
+ if (options.verbose) {
+ return ms.toLocaleString() + " ms";
+ }
+
+ const minutes = Math.floor(ms / MS_IN_MINUTE);
+ const secondsRaw = (ms - minutes * MS_IN_MINUTE) / MS_IN_SECOND;
+ const secondsWhole = Math.floor(secondsRaw);
+ const remainderPrecision = secondsWhole > 0 ? 2 : 3;
+ const secondsRemainder = Math.min(secondsRaw - secondsWhole, 0.99);
+ const seconds =
+ secondsWhole +
+ secondsRemainder
+ .toPrecision(remainderPrecision)
+ .replace(/^0/, "")
+ .replace(/0+$/, "")
+ .replace(/^\.$/, "");
+
+ let time = "";
+
+ if (minutes > 0) time += minutes + " mins, ";
+ time += seconds + " secs";
- if (hours > 0.5) return hours.toFixed(2) + " hours";
- if (minutes > 0.5) return minutes.toFixed(2) + " minutes";
- if (seconds > 0.5) return seconds.toFixed(2) + " seconds";
- return ms.toFixed(0) + " milliseconds";
+ return time;
};
-module.exports.getHumanOutput = outputObj => {
- const delim = "----------------------------";
- let output = delim + "\n";
+module.exports.getHumanOutput = (outputObj, options = {}) => {
+ const hT = x => humanTime(x, options);
+ const smpTag = bg(" SMP ") + " ⏱ ";
+ let output = "\n\n" + smpTag + "\n";
if (outputObj.misc) {
output +=
"General output time took " +
- b(humanTime(outputObj.misc.compileTime), outputObj.misc.compileTime);
+ fg(hT(outputObj.misc.compileTime, options), outputObj.misc.compileTime);
output += "\n\n";
}
if (outputObj.plugins) {
- Object.keys(outputObj.plugins).forEach(pluginName => {
- output +=
- b(pluginName) +
- " took " +
- b(
- humanTime(outputObj.plugins[pluginName]),
- outputObj.plugins[pluginName]
- );
- output += "\n";
- });
+ output += smpTag + " Plugins\n";
+ Object.keys(outputObj.plugins)
+ .sort(
+ (name1, name2) => outputObj.plugins[name2] - outputObj.plugins[name1]
+ )
+ .forEach(pluginName => {
+ output +=
+ fg(pluginName) +
+ " took " +
+ fg(hT(outputObj.plugins[pluginName]), outputObj.plugins[pluginName]);
+ output += "\n";
+ });
output += "\n";
}
if (outputObj.loaders) {
- outputObj.loaders.build.forEach(loaderObj => {
- output +=
- loaderObj.loaders.map(b).join(", and \n") +
- " took " +
- b(humanTime(loaderObj.activeTime), loaderObj.activeTime);
- output += "\n";
- output +=
- " median = " + humanTime(loaderObj.averages.median) + ",\n";
- output +=
- " mean = " + humanTime(loaderObj.averages.mean) + ",\n";
- if (typeof loaderObj.averages.variance === "number")
+ output += smpTag + " Loaders\n";
+ outputObj.loaders.build
+ .sort((obj1, obj2) => obj2.activeTime - obj1.activeTime)
+ .forEach(loaderObj => {
output +=
- " s.d = " +
- humanTime(Math.sqrt(loaderObj.averages.variance)) +
- ", \n";
- output +=
- " range = (" +
- humanTime(loaderObj.averages.range.start) +
- ", " +
- humanTime(loaderObj.averages.range.end) +
- "), \n";
- output += " module count = " + loaderObj.averages.dataPoints + "\n";
- });
+ loaderObj.loaders.map(fg).join(", and \n") +
+ " took " +
+ fg(hT(loaderObj.activeTime), loaderObj.activeTime) +
+ "\n";
+
+ if (options.verbose) {
+ output +=
+ " median = " + hT(loaderObj.averages.median) + ",\n";
+ output += " mean = " + hT(loaderObj.averages.mean) + ",\n";
+ if (typeof loaderObj.averages.variance === "number")
+ output +=
+ " s.d = " +
+ hT(Math.sqrt(loaderObj.averages.variance)) +
+ ", \n";
+ output +=
+ " range = (" +
+ hT(loaderObj.averages.range.start) +
+ " --> " +
+ hT(loaderObj.averages.range.end) +
+ "), \n";
+ }
+
+ output += " module count = " + loaderObj.averages.dataPoints + "\n";
+ });
}
- output += delim + "\n";
+ output += "\n\n";
return output;
};
diff --git a/package.json b/package.json
index e5bba5c..a59d6fb 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "speed-measure-webpack-plugin",
- "version": "0.2.2",
+ "version": "0.3.0",
"description": "Measure + analyse the speed of your webpack loaders and plugins",
"main": "index.js",
"repository": {
diff --git a/preview.png b/preview.png
index b7c1877..8c0b375 100644
Binary files a/preview.png and b/preview.png differ