Skip to content

Commit

Permalink
feat(webpack-cli): stats
Browse files Browse the repository at this point in the history
Amended also the usage of output. `--standard` has been removed and `--pretty` will show the fancy output, which is experimental.
  • Loading branch information
ematipico committed Mar 6, 2020
1 parent a7ecefd commit 1ab8eee
Show file tree
Hide file tree
Showing 27 changed files with 203 additions and 148 deletions.
3 changes: 3 additions & 0 deletions packages/webpack-cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ Options
-h, --hot Enables Hot Module Replacement
-s, --sourcemap string Determine source maps to use
--prefetch string Prefetch this request
--pretty Prints a fancy output
-j, --json Prints result as JSON
--standard Prints standard output
-d, --dev Run development build
Expand All @@ -58,6 +59,8 @@ Options
--no-mode Sets mode="none" which disables any default behavior
--version Get current version
--node-args string[] NodeJS flags
--stats type It instructs webpack on how to treat the stats
--verbose It tells to webpack to output all the information
```

## Defaults
Expand Down
18 changes: 18 additions & 0 deletions packages/webpack-cli/__tests__/StatsGroup.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const StatsGroup = require('../lib/groups/StatsGroup');

describe('StatsGroup', function() {
{
StatsGroup.validOptions().map(option => {
it(`should handle ${option} option`, () => {
const statsGroup = new StatsGroup([
{
stats: option,
},
]);

const result = statsGroup.run();
expect(result.options.stats).toEqual(option);
});
});
}
});
27 changes: 21 additions & 6 deletions packages/webpack-cli/lib/groups/StatsGroup.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,36 @@
const GroupHelper = require('../utils/GroupHelper');

const { logger } = require('@webpack-cli/logger');
/**
* StatsGroup gathers information about the stats options
*/
class StatsGroup extends GroupHelper {
static validOptions() {
return ['minimal', 'none', 'normal', 'verbose', 'errors-warnings', 'errors-only'];
}

constructor(options) {
super(options);
}

resolveOptions() {
Object.keys(this.args).forEach(arg => {
if (['quiet', 'verbose', 'json', 'silent', 'standard'].includes(arg)) {
this.opts.outputOptions[arg] = this.args[arg];
if (this.args.verbose && this.args.stats) {
logger.warn('Conflict between "verbose" and "stats" options. Using verbose.');
this.opts.option.stats = {
verbose: true,
};
} else {
if (this.args.verbose) {
this.opts.option.stats = {
verbose: true,
};
} else {
this.opts.options[arg] = this.args[arg];
this.opts.options.stats = this.args.stats;
}
});
}

if (this.args.pretty) {
this.opts.outputOptions.pretty = true;
}
}

run() {
Expand Down
6 changes: 3 additions & 3 deletions packages/webpack-cli/lib/utils/Compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,7 @@ class Compiler {
}

generateOutput(outputOptions, stats, statsErrors, processingMessageBuffer) {
if (outputOptions.standard) {
this.output.generateRawOutput(stats);
} else {
if (outputOptions.pretty) {
const statsObj = stats.toJson(outputOptions);
if (statsObj.children && Array.isArray(statsObj.children) && this.compilerOptions && Array.isArray(this.compilerOptions)) {
statsObj.children.forEach(child => {
Expand All @@ -89,6 +87,8 @@ class Compiler {
return;
}
this.output.generateFancyOutput(statsObj, statsErrors, processingMessageBuffer);
} else {
this.output.generateRawOutput(stats, this.compilerOptions);
}
process.stdout.write('\n');
if (outputOptions.watch) {
Expand Down
4 changes: 2 additions & 2 deletions packages/webpack-cli/lib/utils/CompilerOutput.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ class CompilerOutput {
return statsObj;
}

generateRawOutput(stats) {
process.stdout.write(stats.toString());
generateRawOutput(stats, options) {
process.stdout.write(stats.toString(options.stats));
}

generateJsonOutput() {}
Expand Down
36 changes: 30 additions & 6 deletions packages/webpack-cli/lib/utils/cli-flags.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
const { logger } = require('@webpack-cli/logger');
const StatsGroup = require('../groups/StatsGroup');

const HELP_GROUP = 'help';
const CONFIG_GROUP = 'config';
const BASIC_GROUP = 'basic';
Expand Down Expand Up @@ -242,25 +245,25 @@ module.exports = {
},
{
name: 'prefetch',
usage: '--prefetch <request>',
usage: 'webpack --prefetch <request>',
type: String,
group: ADVANCED_GROUP,
description: 'Prefetch this request',
link: 'https://webpack.js.org/plugins/prefetch-plugin/',
},
{
name: 'json',
usage: '--json',
usage: 'webpack --json',
type: Boolean,
alias: 'j',
description: 'Prints result as JSON',
group: DISPLAY_GROUP,
},
{
name: 'standard',
usage: '--standard',
name: 'pretty',
usage: 'webpack --pretty',
type: Boolean,
description: 'Prints standard output',
description: 'Prints a fancy output',
group: DISPLAY_GROUP,
},
{
Expand Down Expand Up @@ -290,7 +293,7 @@ module.exports = {
group: ZERO_CONFIG_GROUP,
description: 'Defines the mode to pass to webpack',
link: 'https://webpack.js.org/concepts/#mode',
acceptedValues: ["development", "production"]
acceptedValues: ['development', 'production'],
},
{
name: 'no-mode',
Expand All @@ -315,6 +318,27 @@ module.exports = {
group: BASIC_GROUP,
description: 'NodeJS flags',
},
{
name: 'stats',
usage: 'webpack --stats verbose',
type: value => {
if (StatsGroup.validOptions().includes(value)) {
return value;
}
logger.warn('No value recognised for "stats" option');
return 'normal';
},
group: DISPLAY_GROUP,
description: 'It instructs webpack on how to treat the stats',
link: 'https://webpack.js.org/configuration/stats/#stats',
},
{
name: 'verbose',
usage: 'webpack --verbose',
type: Boolean,
group: DISPLAY_GROUP,
description: 'It tells to webpack to output all the information',
},
/* {
name: "analyze",
type: Boolean,
Expand Down
10 changes: 10 additions & 0 deletions test/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": ["eslint:recommended", "plugin:node/recommended", "plugin:prettier/recommended"],
"env": {
"node": true,
"es6": true,
"jest": true
},
"plugins": ["node", "prettier"],
"parserOptions": { "ecmaVersion": 2020, "sourceType": "module" }
}
11 changes: 2 additions & 9 deletions test/config-lookup/dotfolder-array/dotfolder-array.test.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,14 @@
'use strict';
const { stat } = require('fs');
const { resolve, sep } = require('path');
const { run, extractSummary } = require('../../utils/test-utils');
const { resolve } = require('path');
const { run } = require('../../utils/test-utils');

describe('dotfolder array config lookup', () => {
it('should find a webpack array configuration in a dotfolder', done => {
const { stdout, stderr } = run(__dirname, [], false);
expect(stderr).not.toBeUndefined();
expect(stdout).not.toBeUndefined();

const summary = extractSummary(stdout);
const outputDir = 'config-lookup/dotfolder-array/dist';
const outDirectoryFromCompiler = summary['Output Directory'].split(sep);
const outDirToMatch = outDirectoryFromCompiler
.slice(outDirectoryFromCompiler.length - 3, outDirectoryFromCompiler.length)
.join('/');
expect(outDirToMatch).toContain(outputDir);
stat(resolve(__dirname, './dist/dist-commonjs.js'), (err, stats) => {
expect(err).toBe(null);
expect(stats.isFile()).toBe(true);
Expand Down
8 changes: 2 additions & 6 deletions test/config-lookup/dotfolder-single/dotfolder-single.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,15 @@
const { stat } = require('fs');
const { resolve } = require('path');

const { run, extractSummary } = require('../../utils/test-utils');
const { run } = require('../../utils/test-utils');

describe('dotfolder single config lookup', () => {
it('should find a webpack configuration in a dotfolder', done => {
const { stdout, stderr } = run(__dirname, [], false);
expect(stderr).not.toBeUndefined();
expect(stdout).not.toBeUndefined();

const summary = extractSummary(stdout);
const outputDir = 'config-lookup/dotfolder-single/dist';

expect(summary['Output Directory']).toContain(outputDir);
expect(stderr).not.toContain('Module not found');
expect(stdout).not.toContain('Module not found');
stat(resolve(__dirname, './dist/main.js'), (err, stats) => {
expect(err).toBe(null);
expect(stats.isFile()).toBe(true);
Expand Down
11 changes: 2 additions & 9 deletions test/config/basic/basic-config.test.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
'use strict';
const { stat } = require('fs');
const { resolve, sep } = require('path');
const { run, extractSummary } = require('../../utils/test-utils');
const { resolve } = require('path');
const { run } = require('../../utils/test-utils');

describe('basic config file', () => {
it('is able to understand and parse a very basic configuration file', done => {
const { stdout, stderr } = run(__dirname, ['-c', resolve(__dirname, 'webpack.config.js'), '--output', './binary/a.bundle.js']);
expect(stderr).toContain('Duplicate flags found, defaulting to last set value');
expect(stdout).not.toBe(undefined);
const summary = extractSummary(stdout);
const outputDir = 'basic/binary';
const outDirectoryFromCompiler = summary['Output Directory'].split(sep);
const outDirToMatch = outDirectoryFromCompiler
.slice(outDirectoryFromCompiler.length - 2, outDirectoryFromCompiler.length)
.join('/');
expect(outDirToMatch).toContain(outputDir);
stat(resolve(__dirname, './binary/a.bundle.js'), (err, stats) => {
expect(err).toBe(null);
expect(stats.isFile()).toBe(true);
Expand Down
14 changes: 4 additions & 10 deletions test/config/empty/empty-config.test.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
'use strict';
const { resolve, sep } = require('path');
const { run, extractSummary } = require('../../utils/test-utils');
const { resolve } = require('path');
const { run } = require('../../utils/test-utils');

describe('config flag with empty config file', () => {
it('should throw error with no configuration or index file', () => {
const { stdout, stderr } = run(__dirname, ['-c', resolve(__dirname, 'webpack.config.js')]);
const summary = extractSummary(stdout);
const outputDir = 'empty/bin';
const outDirectoryFromCompiler = summary['Output Directory'].split(sep);
const outDirToMatch = outDirectoryFromCompiler
.slice(outDirectoryFromCompiler.length - 2, outDirectoryFromCompiler.length)
.join('/');
expect(outDirToMatch).toContain(outputDir);
expect(stderr).toBeTruthy();
expect(stderr).toBeFalsy();
expect(stdout).toBeTruthy();
});
});
13 changes: 3 additions & 10 deletions test/config/type/array/array-config.test.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
'use strict';
const { stat } = require('fs');
const { resolve, sep } = require('path');
const { run, extractSummary } = require('../../../utils/test-utils');
const { resolve } = require('path');
const { run } = require('../../../utils/test-utils');

describe('array configuration', () => {
it('is able to understand a configuration file in array format', done => {
const { stdout } = run(__dirname, ['-c', resolve(__dirname, 'webpack.config.js')], false);
const summary = extractSummary(stdout);
const outputDir = 'type/array/dist';
const outDirectoryFromCompiler = summary['Output Directory'].split(sep);
const outDirToMatch = outDirectoryFromCompiler
.slice(outDirectoryFromCompiler.length - 3, outDirectoryFromCompiler.length)
.join('/');
expect(outDirToMatch).toContain(outputDir);
run(__dirname, ['-c', resolve(__dirname, 'webpack.config.js')], false);
stat(resolve(__dirname, './dist/dist-commonjs.js'), (err, stats) => {
expect(err).toBe(null);
expect(stats.isFile()).toBe(true);
Expand Down
13 changes: 3 additions & 10 deletions test/config/type/function/function-config.test.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
'use strict';
const { stat } = require('fs');
const { resolve, sep } = require('path');
const { run, extractSummary } = require('../../../utils/test-utils');
const { resolve } = require('path');
const { run } = require('../../../utils/test-utils');

describe('function configuration', () => {
it('is able to understand a configuration file as a function', done => {
const { stdout } = run(__dirname, ['-c', resolve(__dirname, 'webpack.config.js')], false);
const summary = extractSummary(stdout);
const outputDir = 'type/function/binary';
const outDirectoryFromCompiler = summary['Output Directory'].split(sep);
const outDirToMatch = outDirectoryFromCompiler
.slice(outDirectoryFromCompiler.length - 3, outDirectoryFromCompiler.length)
.join('/');
expect(outDirToMatch).toContain(outputDir);
run(__dirname, ['-c', resolve(__dirname, 'webpack.config.js')], false);
stat(resolve(__dirname, './binary/functor.js'), (err, stats) => {
expect(err).toBe(null);
expect(stats.isFile()).toBe(true);
Expand Down
21 changes: 5 additions & 16 deletions test/defaults/output-defaults.test.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
'use strict';
const { stat } = require('fs');
const { resolve } = require('path');
const { run, extractSummary } = require('../utils/test-utils');
const { run } = require('../utils/test-utils');

describe('output flag defaults', () => {
it('should create default file for a given directory', done => {
const { stdout } = run(__dirname, ['--entry', './a.js', '--output', './binary'], false);
const summary = extractSummary(stdout);
const outputDir = 'defaults/binary';

expect(summary['Output Directory']).toContain(outputDir);
run(__dirname, ['--entry', './a.js', '--output', './binary'], false);

stat(resolve(__dirname, './binary/main.js'), (err, stats) => {
expect(err).toBe(null);
Expand All @@ -18,27 +14,20 @@ describe('output flag defaults', () => {
});
});
it('set default output directory on empty flag', done => {
const { stdout, stderr } = run(__dirname, ['--entry', './a.js', '--output'], false);
const { stdout } = run(__dirname, ['--entry', './a.js', '--output'], false);
// Should print a warning about config fallback since we did not supply --defaults
expect(stderr).toContain('option has not been set, webpack will fallback to');
const summary = extractSummary(stdout);

const outputDir = 'defaults/dist';
expect(stdout).toContain('option has not been set, webpack will fallback to');

expect(summary['Output Directory']).toContain(outputDir);
stat(resolve(__dirname, './dist/main.js'), (err, stats) => {
expect(err).toBe(null);
expect(stats.isFile()).toBe(true);
done();
});
});
it('should not throw when --defaults flag is passed', done => {
const { stdout, stderr } = run(__dirname, ['--defaults'], false);
const summary = extractSummary(stdout);
const outputDir = 'defaults/dist';
const { stderr } = run(__dirname, ['--defaults'], false);
// When using --defaults it should not print warnings about config fallback
expect(stderr).toBeFalsy();
expect(summary['Output Directory']).toContain(outputDir);
stat(resolve(__dirname, './dist/main.js'), (err, stats) => {
expect(err).toBe(null);
expect(stats.isFile()).toBe(true);
Expand Down

0 comments on commit 1ab8eee

Please sign in to comment.