From 34a2e3b4f55612d8de893857af4152a44295ac56 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Tue, 19 Jan 2021 14:30:14 +0300 Subject: [PATCH 01/29] docs: changelog --- CHANGELOG.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60d30584744..92155dfb12a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,23 @@ +# [4.4.0](https://github.com/webpack/webpack-cli/compare/webpack-cli@4.3.1...webpack-cli@4.4.0) (2021-01-19) + +### Bug Fixes + +- better description for `--no-watch-options-stdin` ([#2288](https://github.com/webpack/webpack-cli/issues/2288)) ([4ee8665](https://github.com/webpack/webpack-cli/commit/4ee8665e01e8dce16448e0a4d3dd2293731695ab)) +- double commands output in help ([#2298](https://github.com/webpack/webpack-cli/issues/2298)) ([efe81e9](https://github.com/webpack/webpack-cli/commit/efe81e986a6dca5cc9b72a5c9312dc21409f65b1)) +- pass all `argv` to configurations when `serve` command used ([#2345](https://github.com/webpack/webpack-cli/issues/2345)) ([5070b9b](https://github.com/webpack/webpack-cli/commit/5070b9bcbd5bdac00088d0c21486ad181a4df000)) +- respect `--stats`, `--color` and `--no-color` option for `serve` command ([#2312](https://github.com/webpack/webpack-cli/issues/2312)) ([73d3fec](https://github.com/webpack/webpack-cli/commit/73d3feced18b4e3708f958707326a6642a594cf2)) +- show exact package name while prompting for installation ([#2338](https://github.com/webpack/webpack-cli/issues/2338)) ([ffc93e5](https://github.com/webpack/webpack-cli/commit/ffc93e556d784e2d4409cb0d3a92d737850996f4)) +- webpack installation prompt message ([#2316](https://github.com/webpack/webpack-cli/issues/2316)) ([3659c5e](https://github.com/webpack/webpack-cli/commit/3659c5e529fe1319251ef1c713d6cc758f7f5353)) + +### Features + +- added the `configtest` command ([#2303](https://github.com/webpack/webpack-cli/issues/2303)) ([eb7b189](https://github.com/webpack/webpack-cli/commit/eb7b18937d045261a5b20ca8356e8b4ae4dfcaad)) +- added the `build` command (aliases - `bundle` and `b`) ([7590f66](https://github.com/webpack/webpack-cli/commit/7590f66663ce701d52d9276c3adf9dbdfd1a0fa4)) +- added the `watch` command ([#2357](https://github.com/webpack/webpack-cli/issues/2357)) ([9693f7d](https://github.com/webpack/webpack-cli/commit/9693f7d9543a8fce610c4ef903ccca0d12d229a1)) +- allow to pass parseOption to CLI class ([#2299](https://github.com/webpack/webpack-cli/issues/2299)) ([2af0801](https://github.com/webpack/webpack-cli/commit/2af08013852a95c6f6462c56a9994a4ee28c6ea1)) +- allow to use `help` command to show option information ([#2353](https://github.com/webpack/webpack-cli/issues/2353)) ([15eb411](https://github.com/webpack/webpack-cli/commit/15eb411237dcdcf0db7a501c103fe53f9b82903f)) +- show multiple suggestions on unknown options ([#2349](https://github.com/webpack/webpack-cli/issues/2349)) ([7314d6c](https://github.com/webpack/webpack-cli/commit/7314d6ca927473da2f355a7d356a943471488606)) + ## [4.3.1](https://github.com/webpack/webpack-cli/compare/webpack-cli@4.3.0...webpack-cli@4.3.1) (2020-12-31) ### Bug Fixes From 78074cac284e8230823c32dc43d928324d000847 Mon Sep 17 00:00:00 2001 From: Alexander Akait <4567934+alexander-akait@users.noreply.github.com> Date: Tue, 19 Jan 2021 16:38:46 +0300 Subject: [PATCH 02/29] chore: update `commander` (#2365) --- packages/info/src/index.ts | 7 +- packages/init/src/index.ts | 4 +- packages/serve/src/index.ts | 3 +- packages/webpack-cli/__tests__/CLI.test.js | 212 +++++++++--------- .../lib/utils/capitalize-first-letter.js | 9 + packages/webpack-cli/lib/webpack-cli.js | 20 +- packages/webpack-cli/package.json | 2 +- .../function-with-env.test.js | 2 +- test/defaults/output-defaults.test.js | 2 +- test/info/info-unknown.test.js | 2 +- test/output/output-named-bundles.test.js | 2 +- test/prefetch/prefetch.test.js | 2 +- test/serve/basic/serve-basic.test.js | 4 +- test/target/flag-test/target-flag.test.js | 2 +- test/unknown/unknown.test.js | 40 ++-- yarn.lock | 5 + 16 files changed, 167 insertions(+), 151 deletions(-) create mode 100644 packages/webpack-cli/lib/utils/capitalize-first-letter.js diff --git a/packages/info/src/index.ts b/packages/info/src/index.ts index 83b3884d7c1..3cc41ec587f 100644 --- a/packages/info/src/index.ts +++ b/packages/info/src/index.ts @@ -31,6 +31,8 @@ const DEFAULT_DETAILS: Information = { class InfoCommand { async apply(cli): Promise { + const { logger } = cli; + await cli.makeCommand( { name: 'info', @@ -46,10 +48,9 @@ class InfoCommand { description: 'To get the output in specified format ( accept json or markdown )', }, ], - async (program) => { - let { output } = program.opts(); + async (options) => { + let { output } = options; - const { logger } = cli; const envinfoConfig = {}; if (output) { diff --git a/packages/init/src/index.ts b/packages/init/src/index.ts index 3eb7b545909..077e673053c 100644 --- a/packages/init/src/index.ts +++ b/packages/init/src/index.ts @@ -27,9 +27,7 @@ class InitCommand { description: 'To scaffold in a specified path', }, ], - async (scaffold, program) => { - const options = program.opts(); - + async (scaffold, options) => { if (scaffold && scaffold.length > 0) { await npmPackagesExists(scaffold); diff --git a/packages/serve/src/index.ts b/packages/serve/src/index.ts index ce3c4ebe781..3448af21808 100644 --- a/packages/serve/src/index.ts +++ b/packages/serve/src/index.ts @@ -28,7 +28,7 @@ class ServeCommand { return [...builtInOptions, ...devServerFlags]; }, - async (program) => { + async (options) => { const builtInOptions = cli.getBuiltInOptions(); let devServerFlags = []; @@ -43,7 +43,6 @@ class ServeCommand { const webpackOptions: Record = {}; // eslint-disable-next-line @typescript-eslint/no-explicit-any const devServerOptions: Record = {}; - const options = program.opts(); // eslint-disable-next-line @typescript-eslint/no-explicit-any const processors: Array<(opts: Record) => void> = []; diff --git a/packages/webpack-cli/__tests__/CLI.test.js b/packages/webpack-cli/__tests__/CLI.test.js index 99cae68b35e..348e081893a 100644 --- a/packages/webpack-cli/__tests__/CLI.test.js +++ b/packages/webpack-cli/__tests__/CLI.test.js @@ -11,8 +11,8 @@ describe('CLI API', () => { it('should make command', async (done) => { cli.program.commands = []; - const command = await cli.makeCommand({ name: 'command' }, [], (program) => { - expect(program.opts()).toEqual({}); + const command = await cli.makeCommand({ name: 'command' }, [], (options) => { + expect(options).toEqual({}); done(); }); @@ -33,8 +33,8 @@ describe('CLI API', () => { description: 'description', }, ], - (program) => { - expect(program.opts()).toEqual({ boolean: true }); + (options) => { + expect(options).toEqual({ boolean: true }); done(); }, @@ -57,8 +57,8 @@ describe('CLI API', () => { description: 'description', }, ], - (program) => { - expect(program.opts()).toEqual({ boolean: true }); + (options) => { + expect(options).toEqual({ boolean: true }); done(); }, @@ -82,8 +82,8 @@ describe('CLI API', () => { negative: true, }, ], - (program) => { - expect(program.opts()).toEqual({ boolean: false }); + (options) => { + expect(options).toEqual({ boolean: false }); done(); }, @@ -107,8 +107,8 @@ describe('CLI API', () => { negative: true, }, ], - (program) => { - expect(program.opts()).toEqual({ boolean: false }); + (options) => { + expect(options).toEqual({ boolean: false }); done(); }, @@ -132,8 +132,8 @@ describe('CLI API', () => { negative: true, }, ], - (program) => { - expect(program.opts()).toEqual({ boolean: true }); + (options) => { + expect(options).toEqual({ boolean: true }); done(); }, @@ -157,8 +157,8 @@ describe('CLI API', () => { defaultValue: false, }, ], - (program) => { - expect(program.opts()).toEqual({ boolean: false }); + (options) => { + expect(options).toEqual({ boolean: false }); done(); }, @@ -181,8 +181,8 @@ describe('CLI API', () => { description: 'description', }, ], - (program) => { - expect(program.opts()).toEqual({ string: 'bar' }); + (options) => { + expect(options).toEqual({ string: 'bar' }); done(); }, @@ -206,8 +206,8 @@ describe('CLI API', () => { description: 'description', }, ], - (program) => { - expect(program.opts()).toEqual({ string: 'foo' }); + (options) => { + expect(options).toEqual({ string: 'foo' }); done(); }, @@ -231,8 +231,8 @@ describe('CLI API', () => { defaultValue: 'default-value', }, ], - (program) => { - expect(program.opts()).toEqual({ string: 'default-value' }); + (options) => { + expect(options).toEqual({ string: 'default-value' }); done(); }, @@ -256,8 +256,8 @@ describe('CLI API', () => { defaultValue: 'default-value', }, ], - (program) => { - expect(program.opts()).toEqual({ string: 'foo' }); + (options) => { + expect(options).toEqual({ string: 'foo' }); done(); }, @@ -280,8 +280,8 @@ describe('CLI API', () => { description: 'description', }, ], - (program) => { - expect(program.opts()).toEqual({ string: 'bar' }); + (options) => { + expect(options).toEqual({ string: 'bar' }); done(); }, @@ -305,8 +305,8 @@ describe('CLI API', () => { description: 'description', }, ], - (program) => { - expect(program.opts()).toEqual({ string: ['foo', 'bar'] }); + (options) => { + expect(options).toEqual({ string: ['foo', 'bar'] }); done(); }, @@ -331,8 +331,8 @@ describe('CLI API', () => { defaultValue: 'string', }, ], - (program) => { - expect(program.opts()).toEqual({ string: 'string' }); + (options) => { + expect(options).toEqual({ string: 'string' }); done(); }, @@ -357,8 +357,8 @@ describe('CLI API', () => { defaultValue: 'string', }, ], - (program) => { - expect(program.opts()).toEqual({ string: ['foo', 'bar'] }); + (options) => { + expect(options).toEqual({ string: ['foo', 'bar'] }); done(); }, @@ -382,8 +382,8 @@ describe('CLI API', () => { description: 'description', }, ], - (program) => { - expect(program.opts()).toEqual({ string: ['foo', 'bar'] }); + (options) => { + expect(options).toEqual({ string: ['foo', 'bar'] }); done(); }, @@ -406,8 +406,8 @@ describe('CLI API', () => { description: 'description', }, ], - (program) => { - expect(program.opts()).toEqual({ number: 12 }); + (options) => { + expect(options).toEqual({ number: 12 }); done(); }, @@ -431,8 +431,8 @@ describe('CLI API', () => { defaultValue: 20, }, ], - (program) => { - expect(program.opts()).toEqual({ number: 20 }); + (options) => { + expect(options).toEqual({ number: 20 }); done(); }, @@ -456,8 +456,8 @@ describe('CLI API', () => { description: 'description', }, ], - (program) => { - expect(program.opts()).toEqual({ number: [1, 2] }); + (options) => { + expect(options).toEqual({ number: [1, 2] }); done(); }, @@ -482,8 +482,8 @@ describe('CLI API', () => { defaultValue: 50, }, ], - (program) => { - expect(program.opts()).toEqual({ number: [1, 2] }); + (options) => { + expect(options).toEqual({ number: [1, 2] }); done(); }, @@ -508,8 +508,8 @@ describe('CLI API', () => { defaultValue: 50, }, ], - (program) => { - expect(program.opts()).toEqual({ number: 50 }); + (options) => { + expect(options).toEqual({ number: 50 }); done(); }, @@ -534,8 +534,8 @@ describe('CLI API', () => { description: 'description', }, ], - (program) => { - expect(program.opts()).toEqual({ custom: 'function' }); + (options) => { + expect(options).toEqual({ custom: 'function' }); done(); }, @@ -561,8 +561,8 @@ describe('CLI API', () => { defaultValue: 'default', }, ], - (program) => { - expect(program.opts()).toEqual({ custom: 'default' }); + (options) => { + expect(options).toEqual({ custom: 'default' }); done(); }, @@ -588,8 +588,8 @@ describe('CLI API', () => { multiple: true, }, ], - (program) => { - expect(program.opts()).toEqual({ custom: ['value', 'other'] }); + (options) => { + expect(options).toEqual({ custom: ['value', 'other'] }); done(); }, @@ -616,8 +616,8 @@ describe('CLI API', () => { defaultValue: 50, }, ], - (program) => { - expect(program.opts()).toEqual({ custom: 50 }); + (options) => { + expect(options).toEqual({ custom: 50 }); done(); }, @@ -651,8 +651,8 @@ describe('CLI API', () => { defaultValue: 50, }, ], - (program) => { - expect(program.opts()).toEqual({ custom: ['foo'] }); + (options) => { + expect(options).toEqual({ custom: ['foo'] }); done(); }, @@ -675,8 +675,8 @@ describe('CLI API', () => { description: 'description', }, ], - (program) => { - expect(program.opts()).toEqual({ booleanAndString: true }); + (options) => { + expect(options).toEqual({ booleanAndString: true }); done(); }, @@ -699,8 +699,8 @@ describe('CLI API', () => { description: 'description', }, ], - (program) => { - expect(program.opts()).toEqual({ booleanAndString: 'value' }); + (options) => { + expect(options).toEqual({ booleanAndString: 'value' }); done(); }, @@ -724,8 +724,8 @@ describe('CLI API', () => { multiple: true, }, ], - (program) => { - expect(program.opts()).toEqual({ booleanAndString: true }); + (options) => { + expect(options).toEqual({ booleanAndString: true }); done(); }, @@ -749,8 +749,8 @@ describe('CLI API', () => { multiple: true, }, ], - (program) => { - expect(program.opts()).toEqual({ booleanAndString: ['bar', 'baz'] }); + (options) => { + expect(options).toEqual({ booleanAndString: ['bar', 'baz'] }); done(); }, @@ -774,8 +774,8 @@ describe('CLI API', () => { negative: true, }, ], - (program) => { - expect(program.opts()).toEqual({ booleanAndString: true }); + (options) => { + expect(options).toEqual({ booleanAndString: true }); done(); }, @@ -799,8 +799,8 @@ describe('CLI API', () => { negative: true, }, ], - (program) => { - expect(program.opts()).toEqual({ booleanAndString: 'foo' }); + (options) => { + expect(options).toEqual({ booleanAndString: 'foo' }); done(); }, @@ -824,8 +824,8 @@ describe('CLI API', () => { negative: true, }, ], - (program) => { - expect(program.opts()).toEqual({ booleanAndString: false }); + (options) => { + expect(options).toEqual({ booleanAndString: false }); done(); }, @@ -848,8 +848,8 @@ describe('CLI API', () => { description: 'description', }, ], - (program) => { - expect(program.opts()).toEqual({ booleanAndNumber: true }); + (options) => { + expect(options).toEqual({ booleanAndNumber: true }); done(); }, @@ -872,8 +872,8 @@ describe('CLI API', () => { description: 'description', }, ], - (program) => { - expect(program.opts()).toEqual({ booleanAndNumber: 12 }); + (options) => { + expect(options).toEqual({ booleanAndNumber: 12 }); done(); }, @@ -896,8 +896,8 @@ describe('CLI API', () => { description: 'description', }, ], - (program) => { - expect(program.opts()).toEqual({ boolean: true }); + (options) => { + expect(options).toEqual({ boolean: true }); done(); }, @@ -920,8 +920,8 @@ describe('CLI API', () => { description: 'description', }, ], - (program) => { - expect(program.opts()).toEqual({ booleanAndNumberAndString: true }); + (options) => { + expect(options).toEqual({ booleanAndNumberAndString: true }); done(); }, @@ -944,8 +944,8 @@ describe('CLI API', () => { description: 'description', }, ], - (program) => { - expect(program.opts()).toEqual({ booleanAndNumberAndString: 12 }); + (options) => { + expect(options).toEqual({ booleanAndNumberAndString: 12 }); done(); }, @@ -968,8 +968,8 @@ describe('CLI API', () => { description: 'description', }, ], - (program) => { - expect(program.opts()).toEqual({ booleanAndNumberAndString: 'bar' }); + (options) => { + expect(options).toEqual({ booleanAndNumberAndString: 'bar' }); done(); }, @@ -993,8 +993,8 @@ describe('CLI API', () => { defaultValue: 'default', }, ], - (program) => { - expect(program.opts()).toEqual({ booleanAndNumberAndString: 'default' }); + (options) => { + expect(options).toEqual({ booleanAndNumberAndString: 'default' }); done(); }, @@ -1018,8 +1018,8 @@ describe('CLI API', () => { defaultValue: 'default', }, ], - (program) => { - expect(program.opts()).toEqual({ booleanAndNumberAndString: 'foo' }); + (options) => { + expect(options).toEqual({ booleanAndNumberAndString: 'foo' }); done(); }, @@ -1043,8 +1043,8 @@ describe('CLI API', () => { defaultValue: 'default', }, ], - (program) => { - expect(program.opts()).toEqual({ booleanAndNumberAndString: 12 }); + (options) => { + expect(options).toEqual({ booleanAndNumberAndString: 12 }); done(); }, @@ -1068,8 +1068,8 @@ describe('CLI API', () => { defaultValue: 'default', }, ], - (program) => { - expect(program.opts()).toEqual({ booleanAndNumberAndString: 'default' }); + (options) => { + expect(options).toEqual({ booleanAndNumberAndString: 'default' }); done(); }, @@ -1093,8 +1093,8 @@ describe('CLI API', () => { multiple: true, }, ], - (program) => { - expect(program.opts()).toEqual({ booleanAndNumberAndString: true }); + (options) => { + expect(options).toEqual({ booleanAndNumberAndString: true }); done(); }, @@ -1118,8 +1118,8 @@ describe('CLI API', () => { multiple: true, }, ], - (program) => { - expect(program.opts()).toEqual({ booleanAndNumberAndString: ['foo'] }); + (options) => { + expect(options).toEqual({ booleanAndNumberAndString: ['foo'] }); done(); }, @@ -1143,8 +1143,8 @@ describe('CLI API', () => { multiple: true, }, ], - (program) => { - expect(program.opts()).toEqual({ booleanAndNumberAndString: [12] }); + (options) => { + expect(options).toEqual({ booleanAndNumberAndString: [12] }); done(); }, @@ -1168,8 +1168,8 @@ describe('CLI API', () => { multiple: true, }, ], - (program) => { - expect(program.opts()).toEqual({ booleanAndNumberAndString: ['foo', 'bar'] }); + (options) => { + expect(options).toEqual({ booleanAndNumberAndString: ['foo', 'bar'] }); done(); }, @@ -1193,8 +1193,8 @@ describe('CLI API', () => { multiple: true, }, ], - (program) => { - expect(program.opts()).toEqual({ booleanAndNumberAndString: ['foo', 12] }); + (options) => { + expect(options).toEqual({ booleanAndNumberAndString: ['foo', 12] }); done(); }, @@ -1219,8 +1219,8 @@ describe('CLI API', () => { defaultValue: 'default', }, ], - (program) => { - expect(program.opts()).toEqual({ booleanAndNumberAndString: 'default' }); + (options) => { + expect(options).toEqual({ booleanAndNumberAndString: 'default' }); done(); }, @@ -1245,8 +1245,8 @@ describe('CLI API', () => { defaultValue: 'default', }, ], - (program) => { - expect(program.opts()).toEqual({ booleanAndNumberAndString: ['foo'] }); + (options) => { + expect(options).toEqual({ booleanAndNumberAndString: ['foo'] }); done(); }, @@ -1271,8 +1271,8 @@ describe('CLI API', () => { defaultValue: 'default', }, ], - (program) => { - expect(program.opts()).toEqual({ booleanAndNumberAndString: [12] }); + (options) => { + expect(options).toEqual({ booleanAndNumberAndString: [12] }); done(); }, @@ -1297,8 +1297,8 @@ describe('CLI API', () => { defaultValue: 'default', }, ], - (program) => { - expect(program.opts()).toEqual({ booleanAndNumberAndString: ['foo', 12] }); + (options) => { + expect(options).toEqual({ booleanAndNumberAndString: ['foo', 12] }); done(); }, @@ -1321,8 +1321,8 @@ describe('CLI API', () => { description: 'description', }, ], - (program) => { - expect(program.opts()).toEqual({ unknown: 'foo' }); + (options) => { + expect(options).toEqual({ unknown: 'foo' }); done(); }, diff --git a/packages/webpack-cli/lib/utils/capitalize-first-letter.js b/packages/webpack-cli/lib/utils/capitalize-first-letter.js new file mode 100644 index 00000000000..3ddf802630a --- /dev/null +++ b/packages/webpack-cli/lib/utils/capitalize-first-letter.js @@ -0,0 +1,9 @@ +const capitalizeFirstLetter = (string) => { + if (typeof string !== 'string') { + return ''; + } + + return string.charAt(0).toUpperCase() + string.slice(1); +}; + +module.exports = capitalizeFirstLetter; diff --git a/packages/webpack-cli/lib/webpack-cli.js b/packages/webpack-cli/lib/webpack-cli.js index 3e7427e2658..2de8f796d2e 100644 --- a/packages/webpack-cli/lib/webpack-cli.js +++ b/packages/webpack-cli/lib/webpack-cli.js @@ -10,6 +10,7 @@ const { distance } = require('fastest-levenshtein'); const { options: coloretteOptions, yellow, cyan, green, bold } = require('colorette'); const logger = require('./utils/logger'); +const capitalizeFirstLetter = require('./utils/capitalize-first-letter'); const { cli, flags } = require('./utils/cli-flags'); const CLIPlugin = require('./plugins/CLIPlugin'); const promptInstallation = require('./utils/prompt-installation'); @@ -17,13 +18,18 @@ const toKebabCase = require('./utils/to-kebab-case'); class WebpackCLI { constructor() { - // Initialize program - this.program = program; - this.program.name('webpack'); - this.program.storeOptionsAsProperties(false); + // Global this.webpack = webpack; this.logger = logger; this.utils = { toKebabCase, getPkg, promptInstallation }; + + // Initialize program + this.program = program; + this.program.name('webpack'); + this.program.configureOutput({ + writeErr: logger.error, + outputError: (str, write) => write(`Error: ${capitalizeFirstLetter(str.replace(/^error:/, '').trim())}`), + }); } async makeCommand(commandOptions, options, action) { @@ -357,9 +363,7 @@ class WebpackCLI { await this.makeCommand( isBuildCommandUsed ? buildCommandOptions : watchCommandOptions, this.getBuiltInOptions(), - async (program) => { - const options = program.opts(); - + async (options, program) => { if (program.args.length > 0) { const possibleCommands = [].concat([buildCommandOptions.name]).concat(program.args); @@ -757,7 +761,7 @@ class WebpackCLI { // Default action this.program.usage('[options]'); this.program.allowUnknownOption(true); - this.program.action(async (program) => { + this.program.action(async (_, program) => { if (!isInternalActionCalled) { isInternalActionCalled = true; } else { diff --git a/packages/webpack-cli/package.json b/packages/webpack-cli/package.json index 1e9767a48ca..bbeea374eba 100644 --- a/packages/webpack-cli/package.json +++ b/packages/webpack-cli/package.json @@ -32,7 +32,7 @@ "@webpack-cli/info": "^1.2.1", "@webpack-cli/serve": "^1.2.2", "colorette": "^1.2.1", - "commander": "^6.2.0", + "commander": "^7.0.0", "enquirer": "^2.3.6", "execa": "^5.0.0", "fastest-levenshtein": "^1.0.12", diff --git a/test/config/type/function-with-env/function-with-env.test.js b/test/config/type/function-with-env/function-with-env.test.js index 870cac23548..12a783e31d3 100644 --- a/test/config/type/function-with-env/function-with-env.test.js +++ b/test/config/type/function-with-env/function-with-env.test.js @@ -8,7 +8,7 @@ describe('function configuration', () => { const { exitCode, stderr, stdout } = run(__dirname, ['--env']); expect(exitCode).toBe(2); - expect(stderr).toContain(`option '--env ' argument missing`); + expect(stderr).toContain("Error: Option '--env ' argument missing"); expect(stdout).toBeFalsy(); }); diff --git a/test/defaults/output-defaults.test.js b/test/defaults/output-defaults.test.js index 71f83302c7e..bd4b4213a91 100644 --- a/test/defaults/output-defaults.test.js +++ b/test/defaults/output-defaults.test.js @@ -28,7 +28,7 @@ describe('output flag defaults', () => { const { exitCode, stderr, stdout } = run(__dirname, ['--entry', './a.js', '--output-path'], false); expect(exitCode).toBe(2); - expect(stderr).toContain("error: option '-o, --output-path ' argument missing"); + expect(stderr).toContain("Error: Option '-o, --output-path ' argument missing"); expect(stdout).toBeFalsy(); }); }); diff --git a/test/info/info-unknown.test.js b/test/info/info-unknown.test.js index 545e4d71a55..4846b8f9d7a 100644 --- a/test/info/info-unknown.test.js +++ b/test/info/info-unknown.test.js @@ -5,7 +5,7 @@ describe('should handle unknown args', () => { const { exitCode, stderr, stdout } = run(__dirname, ['info', '--unknown'], false); expect(exitCode).toBe(2); - expect(stderr).toContain("unknown option '--unknown'"); + expect(stderr).toContain("Error: Unknown option '--unknown'"); expect(stdout).toBeFalsy(); }); }); diff --git a/test/output/output-named-bundles.test.js b/test/output/output-named-bundles.test.js index e93e0fe70d5..343dd26ae5c 100644 --- a/test/output/output-named-bundles.test.js +++ b/test/output/output-named-bundles.test.js @@ -52,7 +52,7 @@ describe('output flag named bundles', () => { const { exitCode, stderr, stdout } = run(__dirname, ['--output-path'], false); expect(exitCode).toEqual(2); - expect(stderr).toContain("option '-o, --output-path ' argument missing"); + expect(stderr).toContain("Error: Option '-o, --output-path ' argument missing"); expect(stderr).toContain("Run 'webpack --help' to see available commands and options"); expect(stdout).toBeFalsy(); }); diff --git a/test/prefetch/prefetch.test.js b/test/prefetch/prefetch.test.js index a9404a5a110..1e1a85ab8f7 100644 --- a/test/prefetch/prefetch.test.js +++ b/test/prefetch/prefetch.test.js @@ -33,7 +33,7 @@ describe('prefetch', () => { const { exitCode, stderr, stdout } = run(__dirname, ['--prefetch'], false); expect(exitCode).toBe(2); - expect(stderr).toContain(`error: option '--prefetch ' argument missing`); + expect(stderr).toContain(`Error: Option '--prefetch ' argument missing`); expect(stdout).toBeFalsy(); }); }); diff --git a/test/serve/basic/serve-basic.test.js b/test/serve/basic/serve-basic.test.js index ff5a20998c2..3ad7aa8def4 100644 --- a/test/serve/basic/serve-basic.test.js +++ b/test/serve/basic/serve-basic.test.js @@ -245,7 +245,7 @@ describe('basic serve usage', () => { expect(stdout).toContain('/my-public-path/'); expect(stdout.match(/HotModuleReplacementPlugin/g)).toBeNull(); } else { - expect(stderr).toContain("unknown option '--output-public-path'"); + expect(stderr).toContain("Error: Unknown option '--output-public-path'"); expect(stdout).toBeFalsy(); } }); @@ -311,7 +311,7 @@ describe('basic serve usage', () => { const { exitCode, stdout, stderr } = await runServe(testPath, ['--port', port, '--unknown-flag']); expect(exitCode).toBe(2); - expect(stderr).toContain("unknown option '--unknown-flag'"); + expect(stderr).toContain("Error: Unknown option '--unknown-flag'"); expect(stdout).toBeFalsy(); }); }); diff --git a/test/target/flag-test/target-flag.test.js b/test/target/flag-test/target-flag.test.js index 0705a117cee..0996e9185be 100644 --- a/test/target/flag-test/target-flag.test.js +++ b/test/target/flag-test/target-flag.test.js @@ -59,7 +59,7 @@ describe('--target flag', () => { const { exitCode, stderr, stdout } = run(__dirname, ['--target', 'node', '--target', 'invalid']); expect(exitCode).toBe(2); - expect(stderr).toContain(`Error: Unknown target 'invalid'`); + expect(stderr).toContain("Error: Unknown target 'invalid'"); expect(stdout).toBeFalsy(); }); diff --git a/test/unknown/unknown.test.js b/test/unknown/unknown.test.js index 8f643d63186..ad3b6c97ec3 100644 --- a/test/unknown/unknown.test.js +++ b/test/unknown/unknown.test.js @@ -6,7 +6,7 @@ describe('unknown behaviour', () => { const { exitCode, stderr, stdout } = run(__dirname, ['--unknown']); expect(exitCode).toBe(2); - expect(stderr).toContain("unknown option '--unknown'"); + expect(stderr).toContain("Error: Unknown option '--unknown'"); expect(stderr).toContain("Run 'webpack --help' to see available commands and options"); expect(stdout).toBeFalsy(); }); @@ -15,7 +15,7 @@ describe('unknown behaviour', () => { const { exitCode, stderr, stdout } = run(__dirname, ['-u']); expect(exitCode).toBe(2); - expect(stderr).toContain("unknown option '-u'"); + expect(stderr).toContain("Error: Unknown option '-u'"); expect(stderr).toContain("Run 'webpack --help' to see available commands and options"); expect(stdout).toBeFalsy(); }); @@ -24,7 +24,7 @@ describe('unknown behaviour', () => { const { exitCode, stderr, stdout } = run(__dirname, ['-u', '--unknown']); expect(exitCode).toBe(2); - expect(stderr).toContain("unknown option '-u'"); + expect(stderr).toContain("Error: Unknown option '-u'"); expect(stderr).toContain("Run 'webpack --help' to see available commands and options"); expect(stdout).toBeFalsy(); }); @@ -33,7 +33,7 @@ describe('unknown behaviour', () => { const { exitCode, stderr, stdout } = run(__dirname, ['-u', '-u']); expect(exitCode).toBe(2); - expect(stderr).toContain("unknown option '-u'"); + expect(stderr).toContain("Error: Unknown option '-u'"); expect(stderr).toContain("Run 'webpack --help' to see available commands and options"); expect(stdout).toBeFalsy(); }); @@ -42,7 +42,7 @@ describe('unknown behaviour', () => { const { exitCode, stderr, stdout } = run(__dirname, ['-u', 'foo']); expect(exitCode).toBe(2); - expect(stderr).toContain("unknown option '-u'"); + expect(stderr).toContain("Error: Unknown option '-u'"); expect(stderr).toContain("Run 'webpack --help' to see available commands and options"); expect(stdout).toBeFalsy(); }); @@ -51,7 +51,7 @@ describe('unknown behaviour', () => { const { exitCode, stderr, stdout } = run(__dirname, ['bundle', '--unknown']); expect(exitCode).toBe(2); - expect(stderr).toContain("unknown option '--unknown'"); + expect(stderr).toContain("Error: Unknown option '--unknown'"); expect(stderr).toContain("Run 'webpack --help' to see available commands and options"); expect(stdout).toBeFalsy(); }); @@ -60,7 +60,7 @@ describe('unknown behaviour', () => { const { exitCode, stderr, stdout } = run(__dirname, ['b', '--unknown']); expect(exitCode).toBe(2); - expect(stderr).toContain("unknown option '--unknown'"); + expect(stderr).toContain("Error: Unknown option '--unknown'"); expect(stderr).toContain("Run 'webpack --help' to see available commands and options"); expect(stdout).toBeFalsy(); }); @@ -69,7 +69,7 @@ describe('unknown behaviour', () => { const { exitCode, stderr, stdout } = run(__dirname, ['--unknown', 'bundle']); expect(exitCode).toBe(2); - expect(stderr).toContain("unknown option '--unknown'"); + expect(stderr).toContain("Error: Unknown option '--unknown'"); expect(stderr).toContain("Run 'webpack --help' to see available commands and options"); expect(stdout).toBeFalsy(); }); @@ -78,7 +78,7 @@ describe('unknown behaviour', () => { const { exitCode, stderr, stdout } = run(__dirname, ['info', '--unknown']); expect(exitCode).toBe(2); - expect(stderr).toContain("unknown option '--unknown'"); + expect(stderr).toContain("Error: Unknown option '--unknown'"); expect(stderr).toContain("Run 'webpack --help' to see available commands and options"); expect(stdout).toBeFalsy(); }); @@ -87,7 +87,7 @@ describe('unknown behaviour', () => { const { exitCode, stderr, stdout } = run(__dirname, ['i', '--unknown']); expect(exitCode).toBe(2); - expect(stderr).toContain("unknown option '--unknown'"); + expect(stderr).toContain("Error: Unknown option '--unknown'"); expect(stderr).toContain("Run 'webpack --help' to see available commands and options"); expect(stdout).toBeFalsy(); }); @@ -96,7 +96,7 @@ describe('unknown behaviour', () => { const { exitCode, stderr, stdout } = run(__dirname, ['--unknown', 'i']); expect(exitCode).toBe(2); - expect(stderr).toContain("unknown option '--unknown'"); + expect(stderr).toContain("Error: Unknown option '--unknown'"); expect(stderr).toContain("Run 'webpack --help' to see available commands and options"); expect(stdout).toBeFalsy(); }); @@ -105,7 +105,7 @@ describe('unknown behaviour', () => { const { exitCode, stderr, stdout } = run(__dirname, ['--unknown', '--color']); expect(exitCode).toBe(2); - expect(stderr).toContain("unknown option '--unknown'"); + expect(stderr).toContain("Error: Unknown option '--unknown'"); expect(stderr).toContain("\u001b[31mRun 'webpack --help' to see available commands and options"); expect(stdout).toBeFalsy(); }); @@ -114,7 +114,7 @@ describe('unknown behaviour', () => { const { exitCode, stderr, stdout } = run(__dirname, ['--unknown', '--no-color']); expect(exitCode).toBe(2); - expect(stderr).not.toContain(`\u001b[31munknown option '--unknown'`); + expect(stderr).not.toContain(`\u001b[31mError: Unknown option '--unknown'`); expect(stderr).not.toContain("\u001b[31mRun 'webpack --help' to see available commands and options"); expect(stderr).toContain("Run 'webpack --help' to see available commands and options"); expect(stdout).toBeFalsy(); @@ -124,7 +124,7 @@ describe('unknown behaviour', () => { const { exitCode, stderr, stdout } = run(__dirname, ['--entyr', './a.js']); expect(exitCode).toBe(2); - expect(stderr).toContain("unknown option '--entyr'"); + expect(stderr).toContain("Error: Unknown option '--entyr'"); expect(stderr).toContain("Did you mean '--entry'?"); expect(stderr).toContain("Run 'webpack --help' to see available commands and options"); expect(stdout).toBeFalsy(); @@ -134,7 +134,7 @@ describe('unknown behaviour', () => { const { exitCode, stderr, stdout } = run(__dirname, ['--output-fileneme', '[name].js']); expect(exitCode).toBe(2); - expect(stderr).toContain("unknown option '--output-fileneme'"); + expect(stderr).toContain("Error: Unknown option '--output-fileneme'"); if (isWebpack5) { expect(stderr).toContain("Did you mean '--output-filename'?"); @@ -148,7 +148,7 @@ describe('unknown behaviour', () => { const { exitCode, stderr, stdout } = run(__dirname, ['--output-library-auxiliary-comment-commnjs']); expect(exitCode).toBe(2); - expect(stderr).toContain("unknown option '--output-library-auxiliary-comment-commnjs'"); + expect(stderr).toContain("Error: Unknown option '--output-library-auxiliary-comment-commnjs'"); if (isWebpack5) { expect(stderr).toContain("Did you mean '--output-library-auxiliary-comment-commonjs'?"); @@ -163,7 +163,7 @@ describe('unknown behaviour', () => { const { exitCode, stderr, stdout } = run(__dirname, ['bundle', '--entyr', './a.js']); expect(exitCode).toBe(2); - expect(stderr).toContain("unknown option '--entyr'"); + expect(stderr).toContain("Error: Unknown option '--entyr'"); expect(stderr).toContain("Did you mean '--entry'?"); expect(stderr).toContain("Run 'webpack --help' to see available commands and options"); expect(stdout).toBeFalsy(); @@ -173,7 +173,7 @@ describe('unknown behaviour', () => { const { exitCode, stderr, stdout } = run(__dirname, ['b', '--entyr', './a.js']); expect(exitCode).toBe(2); - expect(stderr).toContain("unknown option '--entyr'"); + expect(stderr).toContain("Error: Unknown option '--entyr'"); expect(stderr).toContain("Did you mean '--entry'?"); expect(stderr).toContain("Run 'webpack --help' to see available commands and options"); expect(stdout).toBeFalsy(); @@ -183,7 +183,7 @@ describe('unknown behaviour', () => { const { exitCode, stderr, stdout } = run(__dirname, ['info', '--outpyt']); expect(exitCode).toBe(2); - expect(stderr).toContain("unknown option '--outpyt'"); + expect(stderr).toContain("Error: Unknown option '--outpyt'"); expect(stderr).toContain("Did you mean '--output'?"); expect(stderr).toContain("Run 'webpack --help' to see available commands and options"); expect(stdout).toBeFalsy(); @@ -193,7 +193,7 @@ describe('unknown behaviour', () => { const { exitCode, stderr, stdout } = run(__dirname, ['i', '--outpyt']); expect(exitCode).toBe(2); - expect(stderr).toContain("unknown option '--outpyt'"); + expect(stderr).toContain("Error: Unknown option '--outpyt'"); expect(stderr).toContain("Did you mean '--output'?"); expect(stderr).toContain("Run 'webpack --help' to see available commands and options"); expect(stdout).toBeFalsy(); diff --git a/yarn.lock b/yarn.lock index ca371037d66..ad2dcac08c5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3379,6 +3379,11 @@ commander@^6.2.0: resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA== +commander@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-7.0.0.tgz#3e2bbfd8bb6724760980988fb5b22b7ee6b71ab2" + integrity sha512-ovx/7NkTrnPuIV8sqk/GjUIIM1+iUQeqA3ye2VNpq9sVoiZsooObWlQy+OPWGI17GDaEoybuAGJm6U8yC077BA== + commitlint-config-cz@^0.13.2: version "0.13.2" resolved "https://registry.yarnpkg.com/commitlint-config-cz/-/commitlint-config-cz-0.13.2.tgz#83f98a1217fb9e1e7cedd6d1d4fdb2d1492a867e" From 7600caba420f785b9a841fca6cccfc577e555367 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 20 Jan 2021 14:07:11 +0300 Subject: [PATCH 03/29] chore(deps-dev): bump @types/node from 14.14.21 to 14.14.22 (#2368) Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 14.14.21 to 14.14.22. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index ad2dcac08c5..788b7ec3f93 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1938,9 +1938,9 @@ integrity sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY= "@types/node@*", "@types/node@>= 8", "@types/node@^14.14.6": - version "14.14.21" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.21.tgz#d934aacc22424fe9622ebf6857370c052eae464e" - integrity sha512-cHYfKsnwllYhjOzuC5q1VpguABBeecUp24yFluHpn/BQaVxB1CuQ1FSRZCzrPxrkIfWISXV2LbeoBthLWg0+0A== + version "14.14.22" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.22.tgz#0d29f382472c4ccf3bd96ff0ce47daf5b7b84b18" + integrity sha512-g+f/qj/cNcqKkc3tFqlXOYjrmZA+jNBiDzbP3kH+B+otKFqAdPgVTGP1IeKRdMml/aE69as5S4FqtxAbl+LaMw== "@types/normalize-package-data@^2.4.0": version "2.4.0" From 23ed6c86b86acbcea85e64e0dbf3da52e0a9f56f Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 20 Jan 2021 14:20:03 +0300 Subject: [PATCH 04/29] chore(deps-dev): bump webpack from 5.15.0 to 5.16.0 (#2367) Bumps [webpack](https://github.com/webpack/webpack) from 5.15.0 to 5.16.0. - [Release notes](https://github.com/webpack/webpack/releases) - [Commits](https://github.com/webpack/webpack/compare/v5.15.0...v5.16.0) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 788b7ec3f93..d774a850ff0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11073,9 +11073,9 @@ webpack-sources@^2.1.1: source-map "^0.6.1" webpack@^5.13.0: - version "5.15.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.15.0.tgz#63d7b6228a4e15ee8c89899c2cfdd993e809bdd2" - integrity sha512-y/xG+ONDz78yn3VvP6gAvGr1/gkxOgitvHSXBmquyN8KDtrGEyE3K9WkXOPB7QmfcOBCpO4ELXwNcCYQnEmexA== + version "5.16.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.16.0.tgz#796e093c2d92c229f013aefefde82b50c0572570" + integrity sha512-QOkctcjYfEGxcYg4AzPJafyAQ7ANc266/URkX881uFA7b2k31E0Dmpy1ExfppHOTp1kHDTsRh9sXojVUvgPF0g== dependencies: "@types/eslint-scope" "^3.7.0" "@types/estree" "^0.0.45" From 85648dbd418deaaada11dd8df1b4469fb8b4817a Mon Sep 17 00:00:00 2001 From: Alexander Akait <4567934+alexander-akait@users.noreply.github.com> Date: Wed, 20 Jan 2021 15:28:32 +0300 Subject: [PATCH 05/29] refactor: code (#2366) --- packages/webpack-cli/lib/webpack-cli.js | 80 ++++++++++--------------- 1 file changed, 32 insertions(+), 48 deletions(-) diff --git a/packages/webpack-cli/lib/webpack-cli.js b/packages/webpack-cli/lib/webpack-cli.js index 2de8f796d2e..aac07d43a46 100644 --- a/packages/webpack-cli/lib/webpack-cli.js +++ b/packages/webpack-cli/lib/webpack-cli.js @@ -331,30 +331,6 @@ class WebpackCLI { value === '-h' || value === '--help'; - const getCommandNameAndOptions = (args) => { - let commandName; - const options = []; - - let allowToSearchCommand = true; - - args.forEach((arg) => { - if (!isOption(arg) && allowToSearchCommand) { - commandName = arg; - - allowToSearchCommand = false; - - return; - } - - allowToSearchCommand = false; - - options.push(arg); - }); - - const isDefault = typeof commandName === 'undefined'; - - return { commandName: isDefault ? buildCommandOptions.name : commandName, options, isDefault }; - }; const loadCommandByName = async (commandName, allowToInstall = false) => { const isBuildCommandUsed = isBuildCommand(commandName); const isWatchCommandUsed = isWatchCommand(commandName); @@ -478,13 +454,14 @@ class WebpackCLI { name = name.split('=')[0]; } - const { commandName } = getCommandNameAndOptions(this.program.args); + const { operands } = this.program.parseOptions(this.program.args); + const operand = typeof operands[0] !== 'undefined' ? operands[0] : 'build'; - if (commandName) { - const command = findCommandByName(commandName); + if (operand) { + const command = findCommandByName(operand); if (!command) { - logger.error(`Can't find and load command '${commandName}'`); + logger.error(`Can't find and load command '${operand}'`); logger.error("Run 'webpack --help' to see available commands and options"); process.exit(2); } @@ -761,7 +738,7 @@ class WebpackCLI { // Default action this.program.usage('[options]'); this.program.allowUnknownOption(true); - this.program.action(async (_, program) => { + this.program.action(async (options, program) => { if (!isInternalActionCalled) { isInternalActionCalled = true; } else { @@ -769,18 +746,19 @@ class WebpackCLI { process.exit(2); } - const { commandName, options, isDefault } = getCommandNameAndOptions(program.args); - - const opts = program.opts(); + // Command and options + const { operands, unknown } = this.program.parseOptions(program.args); + const hasOperand = typeof operands[0] !== 'undefined'; + const operand = hasOperand ? operands[0] : 'build'; - const isHelpCommandSyntax = isHelpCommand(commandName); + const isHelpCommandSyntax = isHelpCommand(operand); - if (opts.help || isHelpCommandSyntax) { + if (options.help || isHelpCommandSyntax) { let isVerbose = false; - if (opts.help) { - if (typeof opts.help === 'string') { - if (opts.help !== 'verbose') { + if (options.help) { + if (typeof options.help === 'string') { + if (options.help !== 'verbose') { logger.error("Unknown value for '--help' option, please use '--help=verbose'"); process.exit(2); } @@ -792,26 +770,32 @@ class WebpackCLI { this.program.forHelp = true; const optionsForHelp = [] - .concat(opts.help && !isDefault ? [commandName] : []) - .concat(options) - .concat(isHelpCommandSyntax && typeof opts.color !== 'undefined' ? [opts.color ? '--color' : '--no-color'] : []) - .concat(isHelpCommandSyntax && typeof opts.version !== 'undefined' ? ['--version'] : []); + .concat(options.help && hasOperand ? [operand] : []) + // Syntax `webpack help [command]` + .concat(operands.slice(1)) + // Syntax `webpack help [option]` + .concat(unknown) + .concat(isHelpCommandSyntax && typeof options.color !== 'undefined' ? [options.color ? '--color' : '--no-color'] : []) + .concat(isHelpCommandSyntax && typeof options.version !== 'undefined' ? ['--version'] : []); await outputHelp(optionsForHelp, isVerbose, isHelpCommandSyntax, program); } - if (opts.version || isVersionCommand(commandName)) { - const optionsForVersion = [].concat(opts.version ? [commandName] : []).concat(options); + if (options.version || isVersionCommand(operand)) { + const optionsForVersion = [] + .concat(options.version ? [operand] : []) + .concat(operands.slice(1)) + .concat(unknown); await outputVersion(optionsForVersion, program); } - if (isKnownCommand(commandName)) { - await loadCommandByName(commandName, true); + if (isKnownCommand(operand)) { + await loadCommandByName(operand, true); } else { - logger.error(`Unknown command '${commandName}'`); + logger.error(`Unknown command '${operand}'`); - const found = knownCommands.find((commandOptions) => distance(commandName, getCommandName(commandOptions.name)) < 3); + const found = knownCommands.find((commandOptions) => distance(operand, getCommandName(commandOptions.name)) < 3); if (found) { logger.error( @@ -825,7 +809,7 @@ class WebpackCLI { process.exit(2); } - await this.program.parseAsync([commandName, ...options], { from: 'user' }); + await this.program.parseAsync([operand, ...operands.slice(1), ...unknown], { from: 'user' }); }); await this.program.parseAsync(args, parseOptions); From 53e8a539d842681d6b3e015c57e756fc7b7a3c57 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 21 Jan 2021 17:09:30 +0300 Subject: [PATCH 06/29] chore(deps-dev): bump webpack-bundle-analyzer from 4.3.0 to 4.4.0 (#2371) Bumps [webpack-bundle-analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer) from 4.3.0 to 4.4.0. - [Release notes](https://github.com/webpack-contrib/webpack-bundle-analyzer/releases) - [Changelog](https://github.com/webpack-contrib/webpack-bundle-analyzer/blob/master/CHANGELOG.md) - [Commits](https://github.com/webpack-contrib/webpack-bundle-analyzer/compare/v4.3.0...v4.4.0) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index d774a850ff0..d98aba10c17 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10984,9 +10984,9 @@ webidl-conversions@^6.1.0: integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== webpack-bundle-analyzer@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.3.0.tgz#2f3c0ca9041d5ee47fa418693cf56b4a518b578b" - integrity sha512-J3TPm54bPARx6QG8z4cKBszahnUglcv70+N+8gUqv2I5KOFHJbzBiLx+pAp606so0X004fxM7hqRu10MLjJifA== + version "4.4.0" + resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.4.0.tgz#74013106e7e2b07cbd64f3a5ae847f7e814802c7" + integrity sha512-9DhNa+aXpqdHk8LkLPTBU/dMfl84Y+WE2+KnfI6rSpNRNVKa0VGLjPd2pjFubDeqnWmulFggxmWBxhfJXZnR0g== dependencies: acorn "^8.0.4" acorn-walk "^8.0.0" From 0d30eda2e0345d6e323408218e420bd6d1b090e2 Mon Sep 17 00:00:00 2001 From: Matthias Date: Fri, 22 Jan 2021 05:50:37 -0500 Subject: [PATCH 07/29] docs: mention `-p` in the changelog (#2372) --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 92155dfb12a..ad016fcba6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -219,7 +219,7 @@ ## Refactor -- remove --dev and --prod flags ([#1693](https://github.com/webpack/webpack-cli/pull/1693)) +- remove --dev and --prod flags and their aliases -d and -p ([#1693](https://github.com/webpack/webpack-cli/pull/1693)) - remove duplicate invocation ([#1790](https://github.com/webpack/webpack-cli/pull/1790)) - cliExecuter consumes runCLI ([#1754](https://github.com/webpack/webpack-cli/pull/1754)) - remove --mode flag validation ([#1744](https://github.com/webpack/webpack-cli/pull/1744)) From c5a06f7b58d161f525183c73b96ab339712bb681 Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Tue, 26 Jan 2021 17:09:55 +0530 Subject: [PATCH 08/29] chore: update webpack to 5.17.0 (#2376) --- OPTIONS.md | 126 ++++++++++++++++++++--- package.json | 2 +- packages/webpack-cli/README.md | 70 +++++++------ test/core-flags/experiments-flag.test.js | 45 +++++--- yarn.lock | 17 +-- 5 files changed, 194 insertions(+), 66 deletions(-) diff --git a/OPTIONS.md b/OPTIONS.md index 3fbe2a31dd4..fd2ea885820 100644 --- a/OPTIONS.md +++ b/OPTIONS.md @@ -53,6 +53,11 @@ Options: --no-experiments-async-web-assembly Negative 'experiments-async-web-assembly' option. --experiments-layers Enable module and chunk layers. --no-experiments-layers Negative 'experiments-layers' option. + --experiments-lazy-compilation Compile entrypoints and import()s only when they are accessed. + --no-experiments-lazy-compilation Negative 'experiments-lazy-compilation' option. + --experiments-lazy-compilation-client A custom client. + --experiments-lazy-compilation-entries Enable/disable lazy compilation for entries. + --no-experiments-lazy-compilation-entries Negative 'experiments-lazy-compilation-entries' option. --experiments-output-module Allow output javascript files as module source type. --no-experiments-output-module Negative 'experiments-output-module' option. --experiments-sync-web-assembly Support WebAssembly as synchronous EcmaScript Module (outdated). @@ -89,10 +94,10 @@ Options: --mode Defines the mode to pass to webpack. --module-expr-context-critical Enable warnings for full dynamic dependencies. --no-module-expr-context-critical Negative 'module-expr-context-critical' option. - --module-expr-context-recursive Enable recursive directory lookup for full dynamic dependencies. + --module-expr-context-recursive Enable recursive directory lookup for full dynamic dependencies. Deprecated: This option has moved to 'module.parser.javascript.exprContextRecursive'. --no-module-expr-context-recursive Negative 'module-expr-context-recursive' option. - --module-expr-context-reg-exp Sets the default regular expression for full dynamic dependencies. - --module-expr-context-request Set the default request for full dynamic dependencies. + --module-expr-context-reg-exp Sets the default regular expression for full dynamic dependencies. Deprecated: This option has moved to 'module.parser.javascript.exprContextRegExp'. + --module-expr-context-request Set the default request for full dynamic dependencies. Deprecated: This option has moved to 'module.parser.javascript.exprContextRequest'. --module-generator-asset-data-url-encoding Asset encoding (defaults to base64). --module-generator-asset-data-url-mimetype Asset mimetype (getting from file extension by default). --module-generator-asset-filename Specifies the filename template of output files on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk. @@ -108,6 +113,14 @@ Options: --no-module-parser-javascript-browserify Negative 'module-parser-javascript-browserify' option. --module-parser-javascript-commonjs Enable/disable parsing of CommonJs syntax. --no-module-parser-javascript-commonjs Negative 'module-parser-javascript-commonjs' option. + --module-parser-javascript-commonjs-magic-comments Enable/disable parsing of magic comments in CommonJs syntax. + --no-module-parser-javascript-commonjs-magic-comments Negative 'module-parser-javascript-commonjs-magic-comments' option. + --module-parser-javascript-expr-context-critical Enable warnings for full dynamic dependencies. + --no-module-parser-javascript-expr-context-critical Negative 'module-parser-javascript-expr-context-critical' option. + --module-parser-javascript-expr-context-recursive Enable recursive directory lookup for full dynamic dependencies. + --no-module-parser-javascript-expr-context-recursive Negative 'module-parser-javascript-expr-context-recursive' option. + --module-parser-javascript-expr-context-reg-exp Sets the default regular expression for full dynamic dependencies. + --module-parser-javascript-expr-context-request Set the default request for full dynamic dependencies. --module-parser-javascript-harmony Enable/disable parsing of EcmaScript Modules syntax. --no-module-parser-javascript-harmony Negative 'module-parser-javascript-harmony' option. --module-parser-javascript-import Enable/disable parsing of import() syntax. @@ -126,18 +139,41 @@ Options: --no-module-parser-javascript-require-include Negative 'module-parser-javascript-require-include' option. --module-parser-javascript-require-js Enable/disable parsing of require.js special syntax like require.config, requirejs.config, require.version and requirejs.onError. --no-module-parser-javascript-require-js Negative 'module-parser-javascript-require-js' option. + --module-parser-javascript-strict-export-presence Emit errors instead of warnings when imported names don't exist in imported module. + --no-module-parser-javascript-strict-export-presence Negative 'module-parser-javascript-strict-export-presence' option. + --module-parser-javascript-strict-this-context-on-imports Handle the this context correctly according to the spec for namespace objects. + --no-module-parser-javascript-strict-this-context-on-imports Negative 'module-parser-javascript-strict-this-context-on-imports' option. --module-parser-javascript-system Enable/disable parsing of System.js special syntax like System.import, System.get, System.set and System.register. --no-module-parser-javascript-system Negative 'module-parser-javascript-system' option. + --module-parser-javascript-unknown-context-critical Enable warnings when using the require function in a not statically analyse-able way. + --no-module-parser-javascript-unknown-context-critical Negative 'module-parser-javascript-unknown-context-critical' option. + --module-parser-javascript-unknown-context-recursive Enable recursive directory lookup when using the require function in a not statically analyse-able way. + --no-module-parser-javascript-unknown-context-recursive Negative 'module-parser-javascript-unknown-context-recursive' option. + --module-parser-javascript-unknown-context-reg-exp Sets the regular expression when using the require function in a not statically analyse-able way. + --module-parser-javascript-unknown-context-request Sets the request when using the require function in a not statically analyse-able way. --module-parser-javascript-url Enable/disable parsing of new URL() syntax. --no-module-parser-javascript-url Negative 'module-parser-javascript-url' option. --module-parser-javascript-worker Specify a syntax that should be parsed as WebWorker reference. 'Abc' handles 'new Abc()', 'Abc from xyz' handles 'import { Abc } from "xyz"; new Abc()', 'abc()' handles 'abc()', and combinations are also possible. Disable or configure parsing of WebWorker syntax like new Worker() or navigator.serviceWorker.register(). --module-parser-javascript-worker-reset Clear all items provided in configuration. Disable or configure parsing of WebWorker syntax like new Worker() or navigator.serviceWorker.register(). + --module-parser-javascript-wrapped-context-critical Enable warnings for partial dynamic dependencies. + --no-module-parser-javascript-wrapped-context-critical Negative 'module-parser-javascript-wrapped-context-critical' option. + --module-parser-javascript-wrapped-context-recursive Enable recursive directory lookup for partial dynamic dependencies. + --no-module-parser-javascript-wrapped-context-recursive Negative 'module-parser-javascript-wrapped-context-recursive' option. + --module-parser-javascript-wrapped-context-reg-exp Set the inner regular expression for partial dynamic dependencies. --module-parser-javascript-auto-amd You can pass `false` to disable AMD support. --no-module-parser-javascript-auto-amd Negative 'module-parser-javascript-auto-amd' option. --module-parser-javascript-auto-browserify Enable/disable special handling for browserify bundles. --no-module-parser-javascript-auto-browserify Negative 'module-parser-javascript-auto-browserify' option. --module-parser-javascript-auto-commonjs Enable/disable parsing of CommonJs syntax. --no-module-parser-javascript-auto-commonjs Negative 'module-parser-javascript-auto-commonjs' option. + --module-parser-javascript-auto-commonjs-magic-comments Enable/disable parsing of magic comments in CommonJs syntax. + --no-module-parser-javascript-auto-commonjs-magic-comments Negative 'module-parser-javascript-auto-commonjs-magic-comments' option. + --module-parser-javascript-auto-expr-context-critical Enable warnings for full dynamic dependencies. + --no-module-parser-javascript-auto-expr-context-critical Negative 'module-parser-javascript-auto-expr-context-critical' option. + --module-parser-javascript-auto-expr-context-recursive Enable recursive directory lookup for full dynamic dependencies. + --no-module-parser-javascript-auto-expr-context-recursive Negative 'module-parser-javascript-auto-expr-context-recursive' option. + --module-parser-javascript-auto-expr-context-reg-exp Sets the default regular expression for full dynamic dependencies. + --module-parser-javascript-auto-expr-context-request Set the default request for full dynamic dependencies. --module-parser-javascript-auto-harmony Enable/disable parsing of EcmaScript Modules syntax. --no-module-parser-javascript-auto-harmony Negative 'module-parser-javascript-auto-harmony' option. --module-parser-javascript-auto-import Enable/disable parsing of import() syntax. @@ -156,18 +192,41 @@ Options: --no-module-parser-javascript-auto-require-include Negative 'module-parser-javascript-auto-require-include' option. --module-parser-javascript-auto-require-js Enable/disable parsing of require.js special syntax like require.config, requirejs.config, require.version and requirejs.onError. --no-module-parser-javascript-auto-require-js Negative 'module-parser-javascript-auto-require-js' option. + --module-parser-javascript-auto-strict-export-presence Emit errors instead of warnings when imported names don't exist in imported module. + --no-module-parser-javascript-auto-strict-export-presence Negative 'module-parser-javascript-auto-strict-export-presence' option. + --module-parser-javascript-auto-strict-this-context-on-imports Handle the this context correctly according to the spec for namespace objects. + --no-module-parser-javascript-auto-strict-this-context-on-imports Negative 'module-parser-javascript-auto-strict-this-context-on-imports' option. --module-parser-javascript-auto-system Enable/disable parsing of System.js special syntax like System.import, System.get, System.set and System.register. --no-module-parser-javascript-auto-system Negative 'module-parser-javascript-auto-system' option. + --module-parser-javascript-auto-unknown-context-critical Enable warnings when using the require function in a not statically analyse-able way. + --no-module-parser-javascript-auto-unknown-context-critical Negative 'module-parser-javascript-auto-unknown-context-critical' option. + --module-parser-javascript-auto-unknown-context-recursive Enable recursive directory lookup when using the require function in a not statically analyse-able way. + --no-module-parser-javascript-auto-unknown-context-recursive Negative 'module-parser-javascript-auto-unknown-context-recursive' option. + --module-parser-javascript-auto-unknown-context-reg-exp Sets the regular expression when using the require function in a not statically analyse-able way. + --module-parser-javascript-auto-unknown-context-request Sets the request when using the require function in a not statically analyse-able way. --module-parser-javascript-auto-url Enable/disable parsing of new URL() syntax. --no-module-parser-javascript-auto-url Negative 'module-parser-javascript-auto-url' option. --module-parser-javascript-auto-worker Specify a syntax that should be parsed as WebWorker reference. 'Abc' handles 'new Abc()', 'Abc from xyz' handles 'import { Abc } from "xyz"; new Abc()', 'abc()' handles 'abc()', and combinations are also possible. Disable or configure parsing of WebWorker syntax like new Worker() or navigator.serviceWorker.register(). --module-parser-javascript-auto-worker-reset Clear all items provided in configuration. Disable or configure parsing of WebWorker syntax like new Worker() or navigator.serviceWorker.register(). + --module-parser-javascript-auto-wrapped-context-critical Enable warnings for partial dynamic dependencies. + --no-module-parser-javascript-auto-wrapped-context-critical Negative 'module-parser-javascript-auto-wrapped-context-critical' option. + --module-parser-javascript-auto-wrapped-context-recursive Enable recursive directory lookup for partial dynamic dependencies. + --no-module-parser-javascript-auto-wrapped-context-recursive Negative 'module-parser-javascript-auto-wrapped-context-recursive' option. + --module-parser-javascript-auto-wrapped-context-reg-exp Set the inner regular expression for partial dynamic dependencies. --module-parser-javascript-dynamic-amd You can pass `false` to disable AMD support. --no-module-parser-javascript-dynamic-amd Negative 'module-parser-javascript-dynamic-amd' option. --module-parser-javascript-dynamic-browserify Enable/disable special handling for browserify bundles. --no-module-parser-javascript-dynamic-browserify Negative 'module-parser-javascript-dynamic-browserify' option. --module-parser-javascript-dynamic-commonjs Enable/disable parsing of CommonJs syntax. --no-module-parser-javascript-dynamic-commonjs Negative 'module-parser-javascript-dynamic-commonjs' option. + --module-parser-javascript-dynamic-commonjs-magic-comments Enable/disable parsing of magic comments in CommonJs syntax. + --no-module-parser-javascript-dynamic-commonjs-magic-comments Negative 'module-parser-javascript-dynamic-commonjs-magic-comments' option. + --module-parser-javascript-dynamic-expr-context-critical Enable warnings for full dynamic dependencies. + --no-module-parser-javascript-dynamic-expr-context-critical Negative 'module-parser-javascript-dynamic-expr-context-critical' option. + --module-parser-javascript-dynamic-expr-context-recursive Enable recursive directory lookup for full dynamic dependencies. + --no-module-parser-javascript-dynamic-expr-context-recursive Negative 'module-parser-javascript-dynamic-expr-context-recursive' option. + --module-parser-javascript-dynamic-expr-context-reg-exp Sets the default regular expression for full dynamic dependencies. + --module-parser-javascript-dynamic-expr-context-request Set the default request for full dynamic dependencies. --module-parser-javascript-dynamic-harmony Enable/disable parsing of EcmaScript Modules syntax. --no-module-parser-javascript-dynamic-harmony Negative 'module-parser-javascript-dynamic-harmony' option. --module-parser-javascript-dynamic-import Enable/disable parsing of import() syntax. @@ -186,18 +245,41 @@ Options: --no-module-parser-javascript-dynamic-require-include Negative 'module-parser-javascript-dynamic-require-include' option. --module-parser-javascript-dynamic-require-js Enable/disable parsing of require.js special syntax like require.config, requirejs.config, require.version and requirejs.onError. --no-module-parser-javascript-dynamic-require-js Negative 'module-parser-javascript-dynamic-require-js' option. + --module-parser-javascript-dynamic-strict-export-presence Emit errors instead of warnings when imported names don't exist in imported module. + --no-module-parser-javascript-dynamic-strict-export-presence Negative 'module-parser-javascript-dynamic-strict-export-presence' option. + --module-parser-javascript-dynamic-strict-this-context-on-imports Handle the this context correctly according to the spec for namespace objects. + --no-module-parser-javascript-dynamic-strict-this-context-on-imports Negative 'module-parser-javascript-dynamic-strict-this-context-on-imports' option. --module-parser-javascript-dynamic-system Enable/disable parsing of System.js special syntax like System.import, System.get, System.set and System.register. --no-module-parser-javascript-dynamic-system Negative 'module-parser-javascript-dynamic-system' option. + --module-parser-javascript-dynamic-unknown-context-critical Enable warnings when using the require function in a not statically analyse-able way. + --no-module-parser-javascript-dynamic-unknown-context-critical Negative 'module-parser-javascript-dynamic-unknown-context-critical' option. + --module-parser-javascript-dynamic-unknown-context-recursive Enable recursive directory lookup when using the require function in a not statically analyse-able way. + --no-module-parser-javascript-dynamic-unknown-context-recursive Negative 'module-parser-javascript-dynamic-unknown-context-recursive' option. + --module-parser-javascript-dynamic-unknown-context-reg-exp Sets the regular expression when using the require function in a not statically analyse-able way. + --module-parser-javascript-dynamic-unknown-context-request Sets the request when using the require function in a not statically analyse-able way. --module-parser-javascript-dynamic-url Enable/disable parsing of new URL() syntax. --no-module-parser-javascript-dynamic-url Negative 'module-parser-javascript-dynamic-url' option. --module-parser-javascript-dynamic-worker Specify a syntax that should be parsed as WebWorker reference. 'Abc' handles 'new Abc()', 'Abc from xyz' handles 'import { Abc } from "xyz"; new Abc()', 'abc()' handles 'abc()', and combinations are also possible. Disable or configure parsing of WebWorker syntax like new Worker() or navigator.serviceWorker.register(). --module-parser-javascript-dynamic-worker-reset Clear all items provided in configuration. Disable or configure parsing of WebWorker syntax like new Worker() or navigator.serviceWorker.register(). + --module-parser-javascript-dynamic-wrapped-context-critical Enable warnings for partial dynamic dependencies. + --no-module-parser-javascript-dynamic-wrapped-context-critical Negative 'module-parser-javascript-dynamic-wrapped-context-critical' option. + --module-parser-javascript-dynamic-wrapped-context-recursive Enable recursive directory lookup for partial dynamic dependencies. + --no-module-parser-javascript-dynamic-wrapped-context-recursive Negative 'module-parser-javascript-dynamic-wrapped-context-recursive' option. + --module-parser-javascript-dynamic-wrapped-context-reg-exp Set the inner regular expression for partial dynamic dependencies. --module-parser-javascript-esm-amd You can pass `false` to disable AMD support. --no-module-parser-javascript-esm-amd Negative 'module-parser-javascript-esm-amd' option. --module-parser-javascript-esm-browserify Enable/disable special handling for browserify bundles. --no-module-parser-javascript-esm-browserify Negative 'module-parser-javascript-esm-browserify' option. --module-parser-javascript-esm-commonjs Enable/disable parsing of CommonJs syntax. --no-module-parser-javascript-esm-commonjs Negative 'module-parser-javascript-esm-commonjs' option. + --module-parser-javascript-esm-commonjs-magic-comments Enable/disable parsing of magic comments in CommonJs syntax. + --no-module-parser-javascript-esm-commonjs-magic-comments Negative 'module-parser-javascript-esm-commonjs-magic-comments' option. + --module-parser-javascript-esm-expr-context-critical Enable warnings for full dynamic dependencies. + --no-module-parser-javascript-esm-expr-context-critical Negative 'module-parser-javascript-esm-expr-context-critical' option. + --module-parser-javascript-esm-expr-context-recursive Enable recursive directory lookup for full dynamic dependencies. + --no-module-parser-javascript-esm-expr-context-recursive Negative 'module-parser-javascript-esm-expr-context-recursive' option. + --module-parser-javascript-esm-expr-context-reg-exp Sets the default regular expression for full dynamic dependencies. + --module-parser-javascript-esm-expr-context-request Set the default request for full dynamic dependencies. --module-parser-javascript-esm-harmony Enable/disable parsing of EcmaScript Modules syntax. --no-module-parser-javascript-esm-harmony Negative 'module-parser-javascript-esm-harmony' option. --module-parser-javascript-esm-import Enable/disable parsing of import() syntax. @@ -216,12 +298,27 @@ Options: --no-module-parser-javascript-esm-require-include Negative 'module-parser-javascript-esm-require-include' option. --module-parser-javascript-esm-require-js Enable/disable parsing of require.js special syntax like require.config, requirejs.config, require.version and requirejs.onError. --no-module-parser-javascript-esm-require-js Negative 'module-parser-javascript-esm-require-js' option. + --module-parser-javascript-esm-strict-export-presence Emit errors instead of warnings when imported names don't exist in imported module. + --no-module-parser-javascript-esm-strict-export-presence Negative 'module-parser-javascript-esm-strict-export-presence' option. + --module-parser-javascript-esm-strict-this-context-on-imports Handle the this context correctly according to the spec for namespace objects. + --no-module-parser-javascript-esm-strict-this-context-on-imports Negative 'module-parser-javascript-esm-strict-this-context-on-imports' option. --module-parser-javascript-esm-system Enable/disable parsing of System.js special syntax like System.import, System.get, System.set and System.register. --no-module-parser-javascript-esm-system Negative 'module-parser-javascript-esm-system' option. + --module-parser-javascript-esm-unknown-context-critical Enable warnings when using the require function in a not statically analyse-able way. + --no-module-parser-javascript-esm-unknown-context-critical Negative 'module-parser-javascript-esm-unknown-context-critical' option. + --module-parser-javascript-esm-unknown-context-recursive Enable recursive directory lookup when using the require function in a not statically analyse-able way. + --no-module-parser-javascript-esm-unknown-context-recursive Negative 'module-parser-javascript-esm-unknown-context-recursive' option. + --module-parser-javascript-esm-unknown-context-reg-exp Sets the regular expression when using the require function in a not statically analyse-able way. + --module-parser-javascript-esm-unknown-context-request Sets the request when using the require function in a not statically analyse-able way. --module-parser-javascript-esm-url Enable/disable parsing of new URL() syntax. --no-module-parser-javascript-esm-url Negative 'module-parser-javascript-esm-url' option. --module-parser-javascript-esm-worker Specify a syntax that should be parsed as WebWorker reference. 'Abc' handles 'new Abc()', 'Abc from xyz' handles 'import { Abc } from "xyz"; new Abc()', 'abc()' handles 'abc()', and combinations are also possible. Disable or configure parsing of WebWorker syntax like new Worker() or navigator.serviceWorker.register(). --module-parser-javascript-esm-worker-reset Clear all items provided in configuration. Disable or configure parsing of WebWorker syntax like new Worker() or navigator.serviceWorker.register(). + --module-parser-javascript-esm-wrapped-context-critical Enable warnings for partial dynamic dependencies. + --no-module-parser-javascript-esm-wrapped-context-critical Negative 'module-parser-javascript-esm-wrapped-context-critical' option. + --module-parser-javascript-esm-wrapped-context-recursive Enable recursive directory lookup for partial dynamic dependencies. + --no-module-parser-javascript-esm-wrapped-context-recursive Negative 'module-parser-javascript-esm-wrapped-context-recursive' option. + --module-parser-javascript-esm-wrapped-context-reg-exp Set the inner regular expression for partial dynamic dependencies. --module-rules-compiler Match the child compiler name. --module-rules-dependency Match dependency type. --module-rules-enforce Enforce this rule as pre or post step. @@ -245,23 +342,23 @@ Options: --module-rules-use-options Options passed to a loader. --module-rules-use A loader request. --module-rules-reset Clear all items provided in configuration. A list of rules. - --module-strict-export-presence Emit errors instead of warnings when imported names don't exist in imported module. + --module-strict-export-presence Emit errors instead of warnings when imported names don't exist in imported module. Deprecated: This option has moved to 'module.parser.javascript.strictExportPresence'. --no-module-strict-export-presence Negative 'module-strict-export-presence' option. - --module-strict-this-context-on-imports Handle the this context correctly according to the spec for namespace objects. + --module-strict-this-context-on-imports Handle the this context correctly according to the spec for namespace objects. Deprecated: This option has moved to 'module.parser.javascript.strictThisContextOnImports'. --no-module-strict-this-context-on-imports Negative 'module-strict-this-context-on-imports' option. - --module-unknown-context-critical Enable warnings when using the require function in a not statically analyse-able way. + --module-unknown-context-critical Enable warnings when using the require function in a not statically analyse-able way. Deprecated: This option has moved to 'module.parser.javascript.unknownContextCritical'. --no-module-unknown-context-critical Negative 'module-unknown-context-critical' option. - --module-unknown-context-recursive Enable recursive directory lookup when using the require function in a not statically analyse-able way. + --module-unknown-context-recursive Enable recursive directory lookup when using the require function in a not statically analyse-able way. Deprecated: This option has moved to 'module.parser.javascript.unknownContextRecursive'. --no-module-unknown-context-recursive Negative 'module-unknown-context-recursive' option. - --module-unknown-context-reg-exp Sets the regular expression when using the require function in a not statically analyse-able way. - --module-unknown-context-request Sets the request when using the require function in a not statically analyse-able way. + --module-unknown-context-reg-exp Sets the regular expression when using the require function in a not statically analyse-able way. Deprecated: This option has moved to 'module.parser.javascript.unknownContextRegExp'. + --module-unknown-context-request Sets the request when using the require function in a not statically analyse-able way. Deprecated: This option has moved to 'module.parser.javascript.unknownContextRequest'. --module-unsafe-cache Cache the resolving of module requests. --no-module-unsafe-cache Negative 'module-unsafe-cache' option. - --module-wrapped-context-critical Enable warnings for partial dynamic dependencies. + --module-wrapped-context-critical Enable warnings for partial dynamic dependencies. Deprecated: This option has moved to 'module.parser.javascript.wrappedContextCritical'. --no-module-wrapped-context-critical Negative 'module-wrapped-context-critical' option. - --module-wrapped-context-recursive Enable recursive directory lookup for partial dynamic dependencies. + --module-wrapped-context-recursive Enable recursive directory lookup for partial dynamic dependencies. Deprecated: This option has moved to 'module.parser.javascript.wrappedContextRecursive'. --no-module-wrapped-context-recursive Negative 'module-wrapped-context-recursive' option. - --module-wrapped-context-reg-exp Set the inner regular expression for partial dynamic dependencies. + --module-wrapped-context-reg-exp Set the inner regular expression for partial dynamic dependencies. Deprecated: This option has moved to 'module.parser.javascript.wrappedContextRegExp'. --name Name of the configuration. Used when loading multiple configurations. --node Include polyfills or mocks for various node stuff. --no-node Negative 'node' option. @@ -345,7 +442,7 @@ Options: --output-devtool-namespace Module namespace to use when interpolating filename template string for the sources array in a generated SourceMap. Defaults to `output.library` if not set. It's useful for avoiding runtime collisions in sourcemaps from multiple webpack projects built as libraries. --output-enabled-chunk-loading-types The method of loading chunks (methods included by default are 'jsonp' (web), 'importScripts' (WebWorker), 'require' (sync node.js), 'async-node' (async node.js), but others might be added by plugins). --output-enabled-chunk-loading-types-reset Clear all items provided in configuration. List of chunk loading types enabled for use by entry points. - --output-enabled-library-types Type of library (types included by default are 'var', 'module', 'assign', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins). + --output-enabled-library-types Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins). --output-enabled-library-types-reset Clear all items provided in configuration. List of library types enabled for use by entry points. --output-enabled-wasm-loading-types The method of loading WebAssembly Modules (methods included by default are 'fetch' (web/WebWorker), 'async-node' (node.js), but others might be added by plugins). --output-enabled-wasm-loading-types-reset Clear all items provided in configuration. List of wasm loading types enabled for use by entry points. @@ -395,7 +492,7 @@ Options: --output-library-name-commonjs Name of the exposed commonjs export in the UMD. --output-library-name-root Part of the name of the property exposed globally by a UMD library. --output-library-name-root-reset Clear all items provided in configuration. Name of the property exposed globally by a UMD library. - --output-library-type Type of library (types included by default are 'var', 'module', 'assign', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins). + --output-library-type Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins). --output-library-umd-named-define If `output.libraryTarget` is set to umd and `output.library` is set, setting this to true will name the AMD module. --no-output-library-umd-named-define Negative 'output-library-umd-named-define' option. --output-module Output javascript files as module source type. @@ -571,6 +668,7 @@ Options: --no-stats-chunk-groups Negative 'stats-chunk-groups' option. --stats-chunk-modules Add built modules information to chunk information. --no-stats-chunk-modules Negative 'stats-chunk-modules' option. + --stats-chunk-modules-space Space to display chunk modules (groups will be collapsed to fit this space, value is in number of modules/group). --stats-chunk-origins Add the origins of chunks and chunk merging info. --no-stats-chunk-origins Negative 'stats-chunk-origins' option. --stats-chunk-relations Add information about parent, children and sibling chunks to chunk information. diff --git a/package.json b/package.json index c6592c46c13..f029c615ce4 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ "strip-ansi": "^6.0.0", "ts-jest": "^26.4.3", "typescript": "^4.1.3", - "webpack": "^5.13.0", + "webpack": "^5.17.0", "webpack-bundle-analyzer": "^4.3.0", "webpack-dev-server": "^3.11.1", "yeoman-test": "^2.7.0" diff --git a/packages/webpack-cli/README.md b/packages/webpack-cli/README.md index 788802545db..ca7f2204b8d 100644 --- a/packages/webpack-cli/README.md +++ b/packages/webpack-cli/README.md @@ -63,46 +63,52 @@ npx webpack-cli --help verbose ### Available Commands ``` - bundle | b Run webpack - help | h Display help for commands and options - version | v Output version number of the 'webpack', 'webpack-cli' and other related packages - init | c Initialize a new webpack configuration - migrate | m Migrate a configuration to a new version - loader | l Scaffold a loader repository - plugin | p Scaffold a plugin repository - info | i Outputs information about your system and dependencies - serve | s Run the webpack Dev Server - configtest | t Tests webpack configuration against validation errors. + build|bundle|b [options] Run webpack (default command, can be omitted). + watch|w [options] Run webpack and watch for files changes. + version|v [commands...] Output the version number of 'webpack', 'webpack-cli' and 'webpack-dev-server' and commands. + help|h [command] [option] Display help for commands and options. + serve|s [options] Run the webpack dev server. + info|i [options] Outputs information about your system. + init|c [options] [scaffold...] Initialize a new webpack configuration. + loader|l [output-path] Scaffold a loader. + migrate|m [new-config-path] Migrate a configuration to a new version. + configtest|t [config-path] Tests webpack configuration against validation errors. + plugin|p [output-path] Scaffold a plugin. ``` ### webpack 4 ``` + Options: --analyze It invokes webpack-bundle-analyzer plugin to get bundle information - --entry string[] The entry point(s) of your application. - -c, --config string[] Provide path to webpack configuration file(s) - --config-name string[] Name of the configuration to use - -m, --merge Merge several configurations using webpack-merge - --progress string, boolean Print compilation progress during build - --color Enables colors on console - --no-color Disable colors on console - --env string[] Environment passed to the configuration when it is a function - --name string Name of the configuration. Used when loading multiple configurations - --help Outputs list of supported flags - -o, --output-path string Output location of the generated bundle - -t, --target string[] Sets the build target - -w, --watch Watch for files changes - --no-watch Do not watch for file changes + -c, --config Provide path to a webpack configuration file e.g. ./webpack.config.js. + --config-name Name of the configuration to use. + -m, --merge Merge two or more configurations using 'webpack-merge'. + --env Environment passed to the configuration when it is a function. + --progress [value] Print compilation progress during build. + -j, --json [value] Prints result as JSON or store it in a file. + -d, --devtool Determine source maps to use. + --no-devtool Do not generate source maps. + --entry The entry point(s) of your application e.g. ./src/main.js. -h, --hot Enables Hot Module Replacement --no-hot Disables Hot Module Replacement - -d, --devtool string Controls if and how source maps are generated. - --no-devtool Do not generate source maps - --prefetch string Prefetch this request - -j, --json string, boolean Prints result as JSON or store it in a file - --mode string Defines the mode to pass to webpack - -v, --version Get current version - --stats string, boolean It instructs webpack on how to treat the stats - --no-stats Disables stats output + --mode Defines the mode to pass to webpack. + --name Name of the configuration. Used when loading multiple configurations. + -o, --output-path Output location of the file generated by webpack e.g. ./dist/. + --prefetch Prefetch this request + --stats [value] It instructs webpack on how to treat the stats e.g. verbose. + --no-stats Disable stats output. + -t, --target Sets the build target e.g. node. + -w, --watch Watch for files changes. + --no-watch Do not watch for file changes. + --watch-options-stdin Stop watching when stdin stream has ended. + --no-watch-options-stdin Do not stop watching when stdin stream has ended. + +Global options: + --color Enable colors on console. + --no-color Disable colors on console. + -v, --version Output the version number of 'webpack', 'webpack-cli' and 'webpack-dev-server' and commands. + -h, --help [verbose] Display help for commands and options. ``` ### webpack 5 diff --git a/test/core-flags/experiments-flag.test.js b/test/core-flags/experiments-flag.test.js index 07704d3c825..b7554dff33e 100644 --- a/test/core-flags/experiments-flag.test.js +++ b/test/core-flags/experiments-flag.test.js @@ -8,23 +8,42 @@ const experimentsFlags = flags.filter(({ name }) => name.startsWith('experiments describe('experiments option related flag', () => { experimentsFlags.forEach((flag) => { // extract property name from flag name - const property = flag.name.split('experiments-')[1]; + let property; + + if (flag.name.includes('-lazy-compilation-')) { + property = flag.name.split('experiments-lazy-compilation-')[1]; + } else { + property = flag.name.split('experiments-')[1]; + } + const propName = hyphenToUpperCase(property); - it(`should config ${flag.name} correctly`, () => { - const { exitCode, stderr, stdout } = run(__dirname, [`--${flag.name}`]); + if (flag.type === Boolean) { + it(`should config --${flag.name} correctly`, () => { + const { exitCode, stderr, stdout } = run(__dirname, [`--${flag.name}`]); + + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + + if (flag.name.includes('-lazy-compilation-')) { + expect(stdout).toContain(`lazyCompilation: { ${propName}: true }`); + } else { + expect(stdout).toContain(`${propName}: true`); + } + }); - expect(exitCode).toBe(0); - expect(stderr).toBeFalsy(); - expect(stdout).toContain(`${propName}: true`); - }); + it(`should config --no-${flag.name} correctly`, () => { + const { exitCode, stderr, stdout } = run(__dirname, [`--no-${flag.name}`]); - it(`should config --no-${flag.name} correctly`, () => { - const { exitCode, stderr, stdout } = run(__dirname, [`--no-${flag.name}`]); + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); - expect(exitCode).toBe(0); - expect(stderr).toBeFalsy(); - expect(stdout).toContain(`${propName}: false`); - }); + if (flag.name.includes('-lazy-compilation-')) { + expect(stdout).toContain(`lazyCompilation: { ${propName}: false }`); + } else { + expect(stdout).toContain(`${propName}: false`); + } + }); + } }); }); diff --git a/yarn.lock b/yarn.lock index d98aba10c17..d401919163c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1821,11 +1821,16 @@ "@types/estree" "*" "@types/json-schema" "*" -"@types/estree@*", "@types/estree@^0.0.45": +"@types/estree@*": version "0.0.45" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.45.tgz#e9387572998e5ecdac221950dab3e8c3b16af884" integrity sha512-jnqIUKDUqJbDIUxm0Uj7bnlMnRm1T/eZ9N+AVMqhPgzrba2GhGG5o/jCTwmdPK709nEZsGoMzXEDUjcXHa3W0g== +"@types/estree@^0.0.46": + version "0.0.46" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.46.tgz#0fb6bfbbeabd7a30880504993369c4bf1deab1fe" + integrity sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg== + "@types/expect@^1.20.4": version "1.20.4" resolved "https://registry.yarnpkg.com/@types/expect/-/expect-1.20.4.tgz#8288e51737bf7e3ab5d7c77bfa695883745264e5" @@ -11072,13 +11077,13 @@ webpack-sources@^2.1.1: source-list-map "^2.0.1" source-map "^0.6.1" -webpack@^5.13.0: - version "5.16.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.16.0.tgz#796e093c2d92c229f013aefefde82b50c0572570" - integrity sha512-QOkctcjYfEGxcYg4AzPJafyAQ7ANc266/URkX881uFA7b2k31E0Dmpy1ExfppHOTp1kHDTsRh9sXojVUvgPF0g== +webpack@^5.17.0: + version "5.17.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.17.0.tgz#e92aebad45be25f86f788dc72fc11daacdcfd55d" + integrity sha512-R+IdNEaYcYaACpXZOt7reyc8txBK7J06lOPkX1SbgmeoAnUbyBZivJIksrDBnmMA3wlTWvPcX7DubxELyPB8rA== dependencies: "@types/eslint-scope" "^3.7.0" - "@types/estree" "^0.0.45" + "@types/estree" "^0.0.46" "@webassemblyjs/ast" "1.11.0" "@webassemblyjs/wasm-edit" "1.11.0" "@webassemblyjs/wasm-parser" "1.11.0" From 153d449386ecbf2b9b502fd9b2999bd494f8d256 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 27 Jan 2021 13:38:02 +0300 Subject: [PATCH 09/29] chore(deps-dev): bump webpack from 5.17.0 to 5.18.0 (#2378) Bumps [webpack](https://github.com/webpack/webpack) from 5.17.0 to 5.18.0. - [Release notes](https://github.com/webpack/webpack/releases) - [Commits](https://github.com/webpack/webpack/compare/v5.17.0...v5.18.0) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- yarn.lock | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/yarn.lock b/yarn.lock index d401919163c..0dbfd643050 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1821,12 +1821,7 @@ "@types/estree" "*" "@types/json-schema" "*" -"@types/estree@*": - version "0.0.45" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.45.tgz#e9387572998e5ecdac221950dab3e8c3b16af884" - integrity sha512-jnqIUKDUqJbDIUxm0Uj7bnlMnRm1T/eZ9N+AVMqhPgzrba2GhGG5o/jCTwmdPK709nEZsGoMzXEDUjcXHa3W0g== - -"@types/estree@^0.0.46": +"@types/estree@*", "@types/estree@^0.0.46": version "0.0.46" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.46.tgz#0fb6bfbbeabd7a30880504993369c4bf1deab1fe" integrity sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg== @@ -11078,9 +11073,9 @@ webpack-sources@^2.1.1: source-map "^0.6.1" webpack@^5.17.0: - version "5.17.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.17.0.tgz#e92aebad45be25f86f788dc72fc11daacdcfd55d" - integrity sha512-R+IdNEaYcYaACpXZOt7reyc8txBK7J06lOPkX1SbgmeoAnUbyBZivJIksrDBnmMA3wlTWvPcX7DubxELyPB8rA== + version "5.18.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.18.0.tgz#bbcf13094aa0da0534d513f27d7ee72d74e499c6" + integrity sha512-RmiP/iy6ROvVe/S+u0TrvL/oOmvP+2+Bs8MWjvBwwY/j82Q51XJyDJ75m0QAGntL1Wx6B//Xc0+4VPP/hlNHmw== dependencies: "@types/eslint-scope" "^3.7.0" "@types/estree" "^0.0.46" From 6b3161479578f572f803f579c7e71073eb797184 Mon Sep 17 00:00:00 2001 From: Alexander Akait <4567934+alexander-akait@users.noreply.github.com> Date: Wed, 27 Jan 2021 14:45:38 +0300 Subject: [PATCH 10/29] feat: entries syntax (#2369) --- OPTIONS.md | 40 +- packages/serve/src/index.ts | 10 +- .../webpack-cli/__tests__/resolveArgs.test.js | 20 +- packages/webpack-cli/lib/utils/cli-flags.js | 202 ------ packages/webpack-cli/lib/webpack-cli.js | 669 +++++++++++++----- test/build/basic/basic.test.js | 126 +++- test/build/basic/entry.config.js | 4 + test/build/basic/src/again.js | 1 + test/build/basic/src/entry.js | 1 + test/build/basic/src/other.js | 1 + test/config/absent/config-absent.test.js | 6 +- test/config/invalid-path/invalid-path.test.js | 6 +- .../with-config-path/with-config-path.test.js | 2 +- test/core-flags/experiments-flag.test.js | 5 +- test/core-flags/externals-flags.test.js | 5 +- test/core-flags/module-flags.test.js | 5 +- test/core-flags/optimization-flags.test.js | 5 +- test/core-flags/output-flags.test.js | 5 +- test/core-flags/performance-flags.test.js | 5 +- test/core-flags/resolve-flags.test.js | 5 +- test/core-flags/snapshot-flags.test.js | 5 +- test/core-flags/stats-flags.test.js | 5 +- test/core-flags/watch-flags.test.js | 5 +- test/core-flags/webpack.test.config.js | 1 - test/help/help.test.js | 428 ++++++----- .../config-absent/merge-config-absent.test.js | 4 +- test/serve/basic/serve-basic.test.js | 47 +- test/serve/basic/serve.config.js | 7 + test/serve/basic/src/entry.js | 1 + test/serve/help/serve-help.test.js | 17 +- test/unknown/unknown.test.js | 4 +- test/watch/basic/basic.test.js | 35 + test/watch/basic/src/entry.js | 1 + 33 files changed, 991 insertions(+), 692 deletions(-) delete mode 100644 packages/webpack-cli/lib/utils/cli-flags.js create mode 100644 test/build/basic/entry.config.js create mode 100644 test/build/basic/src/again.js create mode 100644 test/build/basic/src/entry.js create mode 100644 test/build/basic/src/other.js delete mode 100644 test/core-flags/webpack.test.config.js create mode 100644 test/serve/basic/serve.config.js create mode 100644 test/serve/basic/src/entry.js create mode 100644 test/watch/basic/src/entry.js diff --git a/OPTIONS.md b/OPTIONS.md index fd2ea885820..f87c5a7269e 100644 --- a/OPTIONS.md +++ b/OPTIONS.md @@ -1,12 +1,6 @@ ``` -Usage: webpack [options] -Alternative usage: webpack --config [options] -Alternative usage: webpack build [options] -Alternative usage: webpack bundle [options] -Alternative usage: webpack b [options] -Alternative usage: webpack build --config [options] -Alternative usage: webpack bundle --config [options] -Alternative usage: webpack b --config [options] +Usage: webpack [entries...] [options] +Alternative usage to run commands: webpack [command] [options] The build tool for modern web applications. @@ -793,23 +787,23 @@ Options: --no-watch-options-stdin Do not stop watching when stdin stream has ended. Global options: - --color Enable colors on console. - --no-color Disable colors on console. - -v, --version Output the version number of 'webpack', 'webpack-cli' and 'webpack-dev-server' and commands. - -h, --help [verbose] Display help for commands and options. + --color Enable colors on console. + --no-color Disable colors on console. + -v, --version Output the version number of 'webpack', 'webpack-cli' and 'webpack-dev-server' and commands. + -h, --help [verbose] Display help for commands and options. Commands: - build|bundle|b [options] Run webpack (default command, can be omitted). - watch|w [options] Run webpack and watch for files changes. - version|v [commands...] Output the version number of 'webpack', 'webpack-cli' and 'webpack-dev-server' and commands. - help|h [command] [option] Display help for commands and options. - serve|s [options] Run the webpack dev server. - info|i [options] Outputs information about your system. - init|c [options] [scaffold...] Initialize a new webpack configuration. - loader|l [output-path] Scaffold a loader. - migrate|m [new-config-path] Migrate a configuration to a new version. - configtest|t [config-path] Tests webpack configuration against validation errors. - plugin|p [output-path] Scaffold a plugin. + build|bundle|b [entries...] [options] Run webpack (default command, can be omitted). + configtest|t [config-path] Tests webpack configuration against validation errors. + help|h [command] [option] Display help for commands and options. + info|i [options] Outputs information about your system. + init|c [scaffold...] [options] Initialize a new webpack configuration. + loader|l [output-path] Scaffold a loader. + migrate|m [new-config-path] Migrate a configuration to a new version. + plugin|p [output-path] Scaffold a plugin. + serve|s [entries...] [options] Run the webpack dev server. + version|v [commands...] Output the version number of 'webpack', 'webpack-cli' and 'webpack-dev-server' and commands. + watch|w [entries...] [options] Run webpack and watch for files changes. To see list of all supported commands and options run 'webpack --help=verbose'. diff --git a/packages/serve/src/index.ts b/packages/serve/src/index.ts index 3448af21808..5b72fd66a3a 100644 --- a/packages/serve/src/index.ts +++ b/packages/serve/src/index.ts @@ -6,10 +6,10 @@ class ServeCommand { await cli.makeCommand( { - name: 'serve', + name: 'serve [entries...]', alias: 's', description: 'Run the webpack dev server.', - usage: '[options]', + usage: '[entries...] [options]', pkg: '@webpack-cli/serve', dependencies: ['webpack-dev-server'], }, @@ -28,7 +28,7 @@ class ServeCommand { return [...builtInOptions, ...devServerFlags]; }, - async (options) => { + async (entries, options) => { const builtInOptions = cli.getBuiltInOptions(); let devServerFlags = []; @@ -72,6 +72,10 @@ class ServeCommand { processor(devServerOptions); } + if (entries.length > 0) { + webpackOptions.entry = [...entries, ...(webpackOptions.entry || [])]; + } + webpackOptions.argv = { ...options, env: { WEBPACK_SERVE: true, ...options.env } }; const compiler = await cli.createCompiler(webpackOptions); diff --git a/packages/webpack-cli/__tests__/resolveArgs.test.js b/packages/webpack-cli/__tests__/resolveArgs.test.js index 67a1a0feeb1..db8215e98d5 100644 --- a/packages/webpack-cli/__tests__/resolveArgs.test.js +++ b/packages/webpack-cli/__tests__/resolveArgs.test.js @@ -2,24 +2,24 @@ const { resolve } = require('path'); const webpackCLI = require('../lib/webpack-cli'); const targetValues = ['web', 'webworker', 'node', 'async-node', 'node-webkit', 'electron-main', 'electron-renderer', 'electron-preload']; -const applyOptions = new webpackCLI().applyOptions; +const cli = new webpackCLI(); describe('BasicResolver', () => { it('should handle the output option', async () => { - const result = await applyOptions({ options: {} }, { outputPath: './bundle' }); + const result = await cli.applyOptions({ options: {} }, { outputPath: './bundle' }); expect(result.options.output.path).toEqual(resolve('bundle')); }); it('should handle the mode option [production]', async () => { - const result = await applyOptions({ options: {} }, { mode: 'production' }); + const result = await cli.applyOptions({ options: {} }, { mode: 'production' }); expect(result.options).toMatchObject({ mode: 'production' }); expect(result.options.mode).toEqual('production'); }); it('should handle the mode option [development]', async () => { - const result = await applyOptions( + const result = await cli.applyOptions( { options: {} }, { mode: 'development', @@ -31,7 +31,7 @@ describe('BasicResolver', () => { }); it('should handle the mode option [none]', async () => { - const result = await applyOptions( + const result = await cli.applyOptions( { options: {} }, { mode: 'none', @@ -44,34 +44,34 @@ describe('BasicResolver', () => { it('should prefer supplied move flag over NODE_ENV', async () => { process.env.NODE_ENV = 'production'; - const result = await applyOptions({ options: {} }, { mode: 'development' }); + const result = await cli.applyOptions({ options: {} }, { mode: 'development' }); expect(result.options).toMatchObject({ mode: 'development' }); }); it('should prefer supplied move flag over mode from config', async () => { - const result = await applyOptions({ options: { mode: 'development' } }, { mode: 'production' }); + const result = await cli.applyOptions({ options: { mode: 'development' } }, { mode: 'production' }); expect(result.options).toMatchObject({ mode: 'production' }); }); it('should prefer mode form config over NODE_ENV', async () => { process.env.NODE_ENV = 'development'; - const result = await applyOptions({ options: {} }, { mode: 'production' }); + const result = await cli.applyOptions({ options: {} }, { mode: 'production' }); expect(result.options).toMatchObject({ mode: 'production' }); }); it('should prefer mode form flag over NODE_ENV and config', async () => { process.env.NODE_ENV = 'development'; - const result = await applyOptions({ options: {} }, {}); + const result = await cli.applyOptions({ options: {} }, {}); expect(result.options).toMatchObject({ mode: 'development' }); }); targetValues.map((option) => { it(`should handle ${option} option`, async () => { - const result = await applyOptions({ options: {} }, { target: option }); + const result = await cli.applyOptions({ options: {} }, { target: option }); expect(result.options.target).toEqual(option); }); diff --git a/packages/webpack-cli/lib/utils/cli-flags.js b/packages/webpack-cli/lib/utils/cli-flags.js deleted file mode 100644 index 8f3256aebb9..00000000000 --- a/packages/webpack-cli/lib/utils/cli-flags.js +++ /dev/null @@ -1,202 +0,0 @@ -const packageExists = require('./package-exists'); -const cli = packageExists('webpack') ? require('webpack').cli : undefined; - -const minimumHelpFlags = [ - 'config', - 'config-name', - 'merge', - 'env', - 'mode', - 'watch', - 'watch-options-stdin', - 'stats', - 'devtool', - 'entry', - 'target', - 'progress', - 'json', - 'name', - 'output-path', -]; - -const builtInFlags = [ - // For configs - { - name: 'config', - alias: 'c', - type: String, - multiple: true, - description: 'Provide path to a webpack configuration file e.g. ./webpack.config.js.', - }, - { - name: 'config-name', - type: String, - multiple: true, - description: 'Name of the configuration to use.', - }, - { - name: 'merge', - alias: 'm', - type: Boolean, - description: "Merge two or more configurations using 'webpack-merge'.", - }, - // Complex configs - { - name: 'env', - type: (value, previous = {}) => { - // This ensures we're only splitting by the first `=` - const [allKeys, val] = value.split(/=(.+)/, 2); - const splitKeys = allKeys.split(/\.(?!$)/); - - let prevRef = previous; - - splitKeys.forEach((someKey, index) => { - if (!prevRef[someKey]) { - prevRef[someKey] = {}; - } - - if (typeof prevRef[someKey] === 'string') { - prevRef[someKey] = {}; - } - - if (index === splitKeys.length - 1) { - prevRef[someKey] = val || true; - } - - prevRef = prevRef[someKey]; - }); - - return previous; - }, - multiple: true, - description: 'Environment passed to the configuration when it is a function.', - }, - - // Adding more plugins - { - name: 'hot', - alias: 'h', - type: Boolean, - negative: true, - description: 'Enables Hot Module Replacement', - negatedDescription: 'Disables Hot Module Replacement.', - }, - { - name: 'analyze', - type: Boolean, - multiple: false, - description: 'It invokes webpack-bundle-analyzer plugin to get bundle information.', - }, - { - name: 'progress', - type: [Boolean, String], - description: 'Print compilation progress during build.', - }, - { - name: 'prefetch', - type: String, - description: 'Prefetch this request.', - }, - - // Output options - { - name: 'json', - type: [String, Boolean], - alias: 'j', - description: 'Prints result as JSON or store it in a file.', - }, - - // For webpack@4 - { - name: 'entry', - type: String, - multiple: true, - description: 'The entry point(s) of your application e.g. ./src/main.js.', - }, - { - name: 'output-path', - alias: 'o', - type: String, - description: 'Output location of the file generated by webpack e.g. ./dist/.', - }, - { - name: 'target', - alias: 't', - type: String, - multiple: cli !== undefined, - description: 'Sets the build target e.g. node.', - }, - { - name: 'devtool', - type: String, - negative: true, - alias: 'd', - description: 'Determine source maps to use.', - negatedDescription: 'Do not generate source maps.', - }, - { - name: 'mode', - type: String, - description: 'Defines the mode to pass to webpack.', - }, - { - name: 'name', - type: String, - description: 'Name of the configuration. Used when loading multiple configurations.', - }, - { - name: 'stats', - type: [String, Boolean], - negative: true, - description: 'It instructs webpack on how to treat the stats e.g. verbose.', - negatedDescription: 'Disable stats output.', - }, - { - name: 'watch', - type: Boolean, - negative: true, - alias: 'w', - description: 'Watch for files changes.', - negatedDescription: 'Do not watch for file changes.', - }, - { - name: 'watch-options-stdin', - type: Boolean, - negative: true, - description: 'Stop watching when stdin stream has ended.', - negatedDescription: 'Do not stop watching when stdin stream has ended.', - }, -]; - -// Extract all the flags being exported from core. -// A list of cli flags generated by core can be found here https://github.com/webpack/webpack/blob/master/test/__snapshots__/Cli.test.js.snap -const coreFlags = cli - ? Object.entries(cli.getArguments()).map(([flag, meta]) => { - if (meta.simpleType === 'string') { - meta.type = String; - } else if (meta.simpleType === 'number') { - meta.type = Number; - } else { - meta.type = Boolean; - meta.negative = !flag.endsWith('-reset'); - } - - const inBuiltIn = builtInFlags.find((builtInFlag) => builtInFlag.name === flag); - - if (inBuiltIn) { - return { ...meta, name: flag, group: 'core', ...inBuiltIn }; - } - - return { ...meta, name: flag, group: 'core' }; - }) - : []; -const flags = [] - .concat(builtInFlags.filter((builtInFlag) => !coreFlags.find((coreFlag) => builtInFlag.name === coreFlag.name))) - .concat(coreFlags) - .map((option) => { - option.help = minimumHelpFlags.includes(option.name) ? 'minimum' : 'verbose'; - - return option; - }); - -module.exports = { cli, flags }; diff --git a/packages/webpack-cli/lib/webpack-cli.js b/packages/webpack-cli/lib/webpack-cli.js index aac07d43a46..b945f9b189f 100644 --- a/packages/webpack-cli/lib/webpack-cli.js +++ b/packages/webpack-cli/lib/webpack-cli.js @@ -1,17 +1,16 @@ +const fs = require('fs'); +const path = require('path'); + const { program } = require('commander'); const getPkg = require('./utils/package-exists'); const webpack = getPkg('webpack') ? require('webpack') : undefined; -const path = require('path'); -const { merge } = require('webpack-merge'); -const { extensions, jsVariants } = require('interpret'); +const interpret = require('interpret'); const rechoir = require('rechoir'); -const { createWriteStream, existsSync } = require('fs'); const { distance } = require('fastest-levenshtein'); const { options: coloretteOptions, yellow, cyan, green, bold } = require('colorette'); const logger = require('./utils/logger'); const capitalizeFirstLetter = require('./utils/capitalize-first-letter'); -const { cli, flags } = require('./utils/cli-flags'); const CLIPlugin = require('./plugins/CLIPlugin'); const promptInstallation = require('./utils/prompt-installation'); const toKebabCase = require('./utils/to-kebab-case'); @@ -85,7 +84,9 @@ class WebpackCLI { try { await promptInstallation(dependency, () => { logger.error( - `For using '${green(commandOptions.name)}' command you need to install: '${green(dependency)}' package`, + `For using '${green(commandOptions.name.split(' ')[0])}' command you need to install: '${green( + dependency, + )}' package`, ); }); } catch (error) { @@ -226,22 +227,219 @@ class WebpackCLI { } getBuiltInOptions() { - return flags; + const minimumHelpFlags = [ + 'config', + 'config-name', + 'merge', + 'env', + 'mode', + 'watch', + 'watch-options-stdin', + 'stats', + 'devtool', + 'entry', + 'target', + 'progress', + 'json', + 'name', + 'output-path', + ]; + + const builtInFlags = [ + // For configs + { + name: 'config', + alias: 'c', + type: String, + multiple: true, + description: 'Provide path to a webpack configuration file e.g. ./webpack.config.js.', + }, + { + name: 'config-name', + type: String, + multiple: true, + description: 'Name of the configuration to use.', + }, + { + name: 'merge', + alias: 'm', + type: Boolean, + description: "Merge two or more configurations using 'webpack-merge'.", + }, + // Complex configs + { + name: 'env', + type: (value, previous = {}) => { + // This ensures we're only splitting by the first `=` + const [allKeys, val] = value.split(/=(.+)/, 2); + const splitKeys = allKeys.split(/\.(?!$)/); + + let prevRef = previous; + + splitKeys.forEach((someKey, index) => { + if (!prevRef[someKey]) { + prevRef[someKey] = {}; + } + + if (typeof prevRef[someKey] === 'string') { + prevRef[someKey] = {}; + } + + if (index === splitKeys.length - 1) { + prevRef[someKey] = val || true; + } + + prevRef = prevRef[someKey]; + }); + + return previous; + }, + multiple: true, + description: 'Environment passed to the configuration when it is a function.', + }, + + // Adding more plugins + { + name: 'hot', + alias: 'h', + type: Boolean, + negative: true, + description: 'Enables Hot Module Replacement', + negatedDescription: 'Disables Hot Module Replacement.', + }, + { + name: 'analyze', + type: Boolean, + multiple: false, + description: 'It invokes webpack-bundle-analyzer plugin to get bundle information.', + }, + { + name: 'progress', + type: [Boolean, String], + description: 'Print compilation progress during build.', + }, + { + name: 'prefetch', + type: String, + description: 'Prefetch this request.', + }, + + // Output options + { + name: 'json', + type: [String, Boolean], + alias: 'j', + description: 'Prints result as JSON or store it in a file.', + }, + + // For webpack@4 + { + name: 'entry', + type: String, + multiple: true, + description: 'The entry point(s) of your application e.g. ./src/main.js.', + }, + { + name: 'output-path', + alias: 'o', + type: String, + description: 'Output location of the file generated by webpack e.g. ./dist/.', + }, + { + name: 'target', + alias: 't', + type: String, + multiple: this.webpack.cli !== undefined, + description: 'Sets the build target e.g. node.', + }, + { + name: 'devtool', + type: String, + negative: true, + alias: 'd', + description: 'Determine source maps to use.', + negatedDescription: 'Do not generate source maps.', + }, + { + name: 'mode', + type: String, + description: 'Defines the mode to pass to webpack.', + }, + { + name: 'name', + type: String, + description: 'Name of the configuration. Used when loading multiple configurations.', + }, + { + name: 'stats', + type: [String, Boolean], + negative: true, + description: 'It instructs webpack on how to treat the stats e.g. verbose.', + negatedDescription: 'Disable stats output.', + }, + { + name: 'watch', + type: Boolean, + negative: true, + alias: 'w', + description: 'Watch for files changes.', + negatedDescription: 'Do not watch for file changes.', + }, + { + name: 'watch-options-stdin', + type: Boolean, + negative: true, + description: 'Stop watching when stdin stream has ended.', + negatedDescription: 'Do not stop watching when stdin stream has ended.', + }, + ]; + + // Extract all the flags being exported from core. + // A list of cli flags generated by core can be found here https://github.com/webpack/webpack/blob/master/test/__snapshots__/Cli.test.js.snap + const coreFlags = this.webpack.cli + ? Object.entries(this.webpack.cli.getArguments()).map(([flag, meta]) => { + if (meta.simpleType === 'string') { + meta.type = String; + } else if (meta.simpleType === 'number') { + meta.type = Number; + } else { + meta.type = Boolean; + meta.negative = !flag.endsWith('-reset'); + } + + const inBuiltIn = builtInFlags.find((builtInFlag) => builtInFlag.name === flag); + + if (inBuiltIn) { + return { ...meta, name: flag, group: 'core', ...inBuiltIn }; + } + + return { ...meta, name: flag, group: 'core' }; + }) + : []; + + return [] + .concat(builtInFlags.filter((builtInFlag) => !coreFlags.find((coreFlag) => builtInFlag.name === coreFlag.name))) + .concat(coreFlags) + .map((option) => { + option.help = minimumHelpFlags.includes(option.name) ? 'minimum' : 'verbose'; + + return option; + }); } async run(args, parseOptions) { // Built-in internal commands const buildCommandOptions = { - name: 'build', + name: 'build [entries...]', alias: ['bundle', 'b'], description: 'Run webpack (default command, can be omitted).', - usage: '[options]', + usage: '[entries...] [options]', }; const watchCommandOptions = { - name: 'watch', + name: 'watch [entries...]', alias: 'w', description: 'Run webpack and watch for files changes.', - usage: '[options]', + usage: '[entries...] [options]', }; const versionCommandOptions = { name: 'version [commands...]', @@ -256,7 +454,7 @@ class WebpackCLI { // Built-in external commands const externalBuiltInCommandsInfo = [ { - name: 'serve', + name: 'serve [entries...]', alias: 's', pkg: '@webpack-cli/serve', }, @@ -306,20 +504,23 @@ class WebpackCLI { getCommandName(command.name) === name || (Array.isArray(command.alias) ? command.alias.includes(name) : command.alias === name), ); - const isBuildCommand = (name) => - getCommandName(buildCommandOptions.name) === name || - (Array.isArray(buildCommandOptions.alias) ? buildCommandOptions.alias.includes(name) : buildCommandOptions.alias === name); - const isWatchCommand = (name) => - getCommandName(watchCommandOptions.name) === name || - (Array.isArray(watchCommandOptions.alias) ? watchCommandOptions.alias.includes(name) : watchCommandOptions.alias === name); - const isHelpCommand = (name) => - getCommandName(helpCommandOptions.name) === name || - (Array.isArray(helpCommandOptions.alias) ? helpCommandOptions.alias.includes(name) : helpCommandOptions.alias === name); - const isVersionCommand = (name) => - getCommandName(versionCommandOptions.name) === name || - (Array.isArray(versionCommandOptions.alias) - ? versionCommandOptions.alias.includes(name) - : versionCommandOptions.alias === name); + const isCommand = (input, commandOptions) => { + const longName = getCommandName(commandOptions.name); + + if (input === longName) { + return true; + } + + if (commandOptions.alias) { + if (Array.isArray(commandOptions.alias)) { + return commandOptions.alias.includes(input); + } else { + return commandOptions.alias === input; + } + } + + return false; + }; const findCommandByName = (name) => this.program.commands.find((command) => name === command.name() || command.alias().includes(name)); const isOption = (value) => value.startsWith('-'); @@ -332,21 +533,16 @@ class WebpackCLI { value === '--help'; const loadCommandByName = async (commandName, allowToInstall = false) => { - const isBuildCommandUsed = isBuildCommand(commandName); - const isWatchCommandUsed = isWatchCommand(commandName); + const isBuildCommandUsed = isCommand(commandName, buildCommandOptions); + const isWatchCommandUsed = isCommand(commandName, watchCommandOptions); if (isBuildCommandUsed || isWatchCommandUsed) { await this.makeCommand( isBuildCommandUsed ? buildCommandOptions : watchCommandOptions, this.getBuiltInOptions(), - async (options, program) => { - if (program.args.length > 0) { - const possibleCommands = [].concat([buildCommandOptions.name]).concat(program.args); - - logger.error('Running multiple commands at the same time is not possible'); - logger.error(`Found commands: ${possibleCommands.map((item) => `'${item}'`).join(', ')}`); - logger.error("Run 'webpack --help' to see available commands and options"); - process.exit(2); + async (entries, options) => { + if (entries.length > 0) { + options.entry = [...entries, ...(options.entry || [])]; } if (isWatchCommandUsed) { @@ -361,13 +557,13 @@ class WebpackCLI { options.watch = true; } - await this.bundleCommand(options); + await this.buildCommand(options); }, ); - } else if (isHelpCommand(commandName)) { + } else if (isCommand(commandName, helpCommandOptions)) { // Stub for the `help` command this.makeCommand(helpCommandOptions, [], () => {}); - } else if (isVersionCommand(commandName)) { + } else if (isCommand(commandName, versionCommandOptions)) { // Stub for the `help` command this.makeCommand(versionCommandOptions, [], () => {}); } else { @@ -455,7 +651,7 @@ class WebpackCLI { } const { operands } = this.program.parseOptions(this.program.args); - const operand = typeof operands[0] !== 'undefined' ? operands[0] : 'build'; + const operand = typeof operands[0] !== 'undefined' ? operands[0] : getCommandName(buildCommandOptions.name); if (operand) { const command = findCommandByName(operand); @@ -506,7 +702,11 @@ class WebpackCLI { const outputVersion = async (options) => { // Filter `bundle`, `watch`, `version` and `help` commands const possibleCommandNames = options.filter( - (option) => !isBuildCommand(option) && !isWatchCommand(option) && !isVersionCommand(option) && !isHelpCommand(option), + (option) => + !isCommand(option, buildCommandOptions) && + !isCommand(option, watchCommandOptions) && + !isCommand(option, versionCommandOptions) && + !isCommand(option, helpCommandOptions), ); possibleCommandNames.forEach((possibleCommandName) => { @@ -544,7 +744,7 @@ class WebpackCLI { const pkgJSON = require('../package.json'); - logger.raw(`webpack ${webpack.version}`); + logger.raw(`webpack ${this.webpack.version}`); logger.raw(`webpack-cli ${pkgJSON.version}`); if (getPkg('webpack-dev-server')) { @@ -562,46 +762,6 @@ class WebpackCLI { ); const outputHelp = async (options, isVerbose, isHelpCommandSyntax, program) => { - const hideVerboseOptions = (command) => { - command.options = command.options.filter((option) => { - const foundOption = flags.find((flag) => { - if (option.negate && flag.negative) { - return `no-${flag.name}` === option.name(); - } - - return flag.name === option.name(); - }); - - if (foundOption && foundOption.help) { - return foundOption.help === 'minimum'; - } - - return true; - }); - }; - const outputGlobalOptions = () => { - const programHelpInformation = program.helpInformation(); - const globalOptions = programHelpInformation.match(/Options:\n(?.+)\nCommands:\n/s); - - if (globalOptions && globalOptions.groups.globalOptions) { - logger.raw('\nGlobal options:'); - logger.raw(globalOptions.groups.globalOptions.trimRight()); - } - }; - const outputGlobalCommands = () => { - const programHelpInformation = program.helpInformation(); - const globalCommands = programHelpInformation.match(/Commands:\n(?.+)/s); - - if (globalCommands.groups.globalCommands) { - logger.raw('\nCommands:'); - logger.raw( - globalCommands.groups.globalCommands - .trimRight() - // `commander` doesn't support multiple alias in help - .replace('build|bundle [options] ', 'build|bundle|b [options]'), - ); - } - }; const outputIncorrectUsageOfHelp = () => { logger.error('Incorrect use of help'); logger.error("Please use: 'webpack help [command] [option]' | 'webpack [command] --help'"); @@ -609,61 +769,177 @@ class WebpackCLI { process.exit(2); }; - if (options.length === 0) { - await Promise.all( - knownCommands.map((knownCommand) => { - return loadCommandByName(getCommandName(knownCommand.name)); - }), - ); + const isGlobalHelp = options.length === 0; + const isCommandHelp = options.length === 1 && !isOption(options[0]); - const bundleCommand = findCommandByName(buildCommandOptions.name); + if (isGlobalHelp || isCommandHelp) { + const cliAPI = this; - if (!isVerbose) { - hideVerboseOptions(bundleCommand); - } + program.configureHelp({ + sortSubcommands: true, + // Support multiple aliases + commandUsage: (command) => { + let parentCmdNames = ''; - let helpInformation = bundleCommand - .helpInformation() - .trimRight() - .replace(buildCommandOptions.description, 'The build tool for modern web applications.') - .replace( - /Usage:.+/, - 'Usage: webpack [options]\nAlternative usage: webpack --config [options]\nAlternative usage: webpack build [options]\nAlternative usage: webpack bundle [options]\nAlternative usage: webpack b [options]\nAlternative usage: webpack build --config [options]\nAlternative usage: webpack bundle --config [options]\nAlternative usage: webpack b --config [options]', - ); + for (let parentCmd = command.parent; parentCmd; parentCmd = parentCmd.parent) { + parentCmdNames = `${parentCmd.name()} ${parentCmdNames}`; + } - logger.raw(helpInformation); + if (isGlobalHelp) { + return `${parentCmdNames}${command.usage()}\n${bold( + 'Alternative usage to run commands:', + )} ${parentCmdNames}[command] [options]`; + } - outputGlobalOptions(); - outputGlobalCommands(); - } else if (options.length === 1 && !isOption(options[0])) { - const name = options[0]; + return `${parentCmdNames}${command.name()}|${command.aliases().join('|')} ${command.usage()}`; + }, + // Support multiple aliases + subcommandTerm: (command) => { + const humanReadableArgumentName = (argument) => { + const nameOutput = argument.name + (argument.variadic === true ? '...' : ''); + + return argument.required ? '<' + nameOutput + '>' : '[' + nameOutput + ']'; + }; + const args = command._args.map((arg) => humanReadableArgumentName(arg)).join(' '); + + return `${command.name()}|${command.aliases().join('|')}${args ? ` ${args}` : ''}${ + command.options.length > 0 ? ' [options]' : '' + }`; + }, + visibleOptions: function visibleOptions(command) { + const options = cliAPI.getBuiltInOptions(); - await loadCommandByName(name); + return command.options.filter((option) => { + if (option.hidden) { + return false; + } - const command = findCommandByName(name); + if (!isVerbose) { + const foundOption = options.find((flag) => { + if (option.negate && flag.negative) { + return `no-${flag.name}` === option.name(); + } - if (!command) { - logger.error(`Can't find and load command '${name}'`); - logger.error("Run 'webpack --help' to see available commands and options"); - process.exit(2); - } + return flag.name === option.name(); + }); - if (!isVerbose) { - hideVerboseOptions(command); - } + if (foundOption) { + return foundOption.help === 'minimum'; + } - let helpInformation = command.helpInformation().trimRight(); + return true; + } - if (isBuildCommand(name)) { - helpInformation = helpInformation.replace('build|bundle', 'build|bundle|b'); - } + return true; + }); + }, + padWidth(command, helper) { + return Math.max( + helper.longestArgumentTermLength(command, helper), + helper.longestOptionTermLength(command, helper), + // For global options + helper.longestOptionTermLength(program, helper), + helper.longestSubcommandTermLength(isGlobalHelp ? program : command, helper), + ); + }, + formatHelp: (command, helper) => { + const termWidth = helper.padWidth(command, helper); + const helpWidth = helper.helpWidth || 80; + const itemIndentWidth = 2; + const itemSeparatorWidth = 2; // between term and description + + const formatItem = (term, description) => { + if (description) { + const fullText = `${term.padEnd(termWidth + itemSeparatorWidth)}${description}`; + + return helper.wrap(fullText, helpWidth - itemIndentWidth, termWidth + itemSeparatorWidth); + } + + return term; + }; + + const formatList = (textArray) => textArray.join('\n').replace(/^/gm, ' '.repeat(itemIndentWidth)); + + // Usage + let output = [`${bold('Usage:')} ${helper.commandUsage(command)}`, '']; + + // Description + const commandDescription = isGlobalHelp + ? 'The build tool for modern web applications.' + : helper.commandDescription(command); + + if (commandDescription.length > 0) { + output = output.concat([commandDescription, '']); + } + + // Arguments + const argumentList = helper + .visibleArguments(command) + .map((argument) => formatItem(argument.term, argument.description)); + + if (argumentList.length > 0) { + output = output.concat([bold('Arguments:'), formatList(argumentList), '']); + } + + // Options + const optionList = helper + .visibleOptions(command) + .map((option) => formatItem(helper.optionTerm(option), helper.optionDescription(option))); + + if (optionList.length > 0) { + output = output.concat([bold('Options:'), formatList(optionList), '']); + } + + // Global options + const globalOptionList = program.options.map((option) => + formatItem(helper.optionTerm(option), helper.optionDescription(option)), + ); + + if (globalOptionList.length > 0) { + output = output.concat([bold('Global options:'), formatList(globalOptionList), '']); + } + + // Commands + const commandList = helper + .visibleCommands(isGlobalHelp ? program : command) + .map((command) => formatItem(helper.subcommandTerm(command), helper.subcommandDescription(command))); + + if (commandList.length > 0) { + output = output.concat([bold('Commands:'), formatList(commandList), '']); + } + + return output.join('\n'); + }, + }); + + if (isGlobalHelp) { + await Promise.all( + knownCommands.map((knownCommand) => { + return loadCommandByName(getCommandName(knownCommand.name)); + }), + ); + + const buildCommand = findCommandByName(getCommandName(buildCommandOptions.name)); + + logger.raw(buildCommand.helpInformation()); + } else { + const name = options[0]; + + await loadCommandByName(name); - logger.raw(helpInformation); + const command = findCommandByName(name); - outputGlobalOptions(); + if (!command) { + logger.error(`Can't find and load command '${name}'`); + logger.error("Run 'webpack --help' to see available commands and options"); + process.exit(2); + } + + logger.raw(command.helpInformation()); + } } else if (isHelpCommandSyntax) { let isCommandSpecified = false; - let commandName = buildCommandOptions.name; + let commandName = getCommandName(buildCommandOptions.name); let optionName; if (options.length === 1) { @@ -682,7 +958,7 @@ class WebpackCLI { await loadCommandByName(commandName); - const command = isGlobalOption(optionName) ? this.program : findCommandByName(commandName); + const command = isGlobalOption(optionName) ? program : findCommandByName(commandName); if (!command) { logger.error(`Can't find and load command '${commandName}'`); @@ -702,20 +978,28 @@ class WebpackCLI { option.flags.replace(/^.+[[<]/, '').replace(/(\.\.\.)?[\]>].*$/, '') + (option.variadic === true ? '...' : ''); const value = option.required ? '<' + nameOutput + '>' : option.optional ? '[' + nameOutput + ']' : ''; - logger.raw(`Usage: webpack${isCommandSpecified ? ` ${commandName}` : ''} ${option.long}${value ? ` ${value}` : ''}`); + logger.raw( + `${bold('Usage')}: webpack${isCommandSpecified ? ` ${commandName}` : ''} ${option.long}${value ? ` ${value}` : ''}`, + ); if (option.short) { - logger.raw(`Short: webpack${isCommandSpecified ? ` ${commandName}` : ''} ${option.short}${value ? ` ${value}` : ''}`); + logger.raw( + `${bold('Short:')} webpack${isCommandSpecified ? ` ${commandName}` : ''} ${option.short}${ + value ? ` ${value}` : '' + }`, + ); } if (option.description) { - logger.raw(`Description: ${option.description}`); + logger.raw(`${bold('Description:')} ${option.description}`); } if (!option.negate && options.defaultValue) { - logger.raw(`Default value: ${JSON.stringify(option.defaultValue)}`); + logger.raw(`${bold('Default value:')} ${JSON.stringify(option.defaultValue)}`); } + logger.raw(''); + // TODO implement this after refactor cli arguments // logger.raw('Possible values: foo | bar'); // logger.raw('Documentation: https://webpack.js.org/option/name/'); @@ -723,9 +1007,9 @@ class WebpackCLI { outputIncorrectUsageOfHelp(); } - logger.raw("\nTo see list of all supported commands and options run 'webpack --help=verbose'.\n"); - logger.raw('Webpack documentation: https://webpack.js.org/.'); - logger.raw('CLI documentation: https://webpack.js.org/api/cli/.'); + logger.raw("To see list of all supported commands and options run 'webpack --help=verbose'.\n"); + logger.raw(`${bold('Webpack documentation:')} https://webpack.js.org/.`); + logger.raw(`${bold('CLI documentation:')} https://webpack.js.org/api/cli/.`); logger.raw(`${bold('Made with ♥ by the webpack team')}.`); process.exit(0); }; @@ -748,10 +1032,11 @@ class WebpackCLI { // Command and options const { operands, unknown } = this.program.parseOptions(program.args); + const defaultCommandToRun = getCommandName(buildCommandOptions.name); const hasOperand = typeof operands[0] !== 'undefined'; - const operand = hasOperand ? operands[0] : 'build'; + const operand = hasOperand ? operands[0] : defaultCommandToRun; - const isHelpCommandSyntax = isHelpCommand(operand); + const isHelpCommandSyntax = isCommand(operand, helpCommandOptions); if (options.help || isHelpCommandSyntax) { let isVerbose = false; @@ -781,7 +1066,7 @@ class WebpackCLI { await outputHelp(optionsForHelp, isVerbose, isHelpCommandSyntax, program); } - if (options.version || isVersionCommand(operand)) { + if (options.version || isCommand(operand, versionCommandOptions)) { const optionsForVersion = [] .concat(options.version ? [operand] : []) .concat(operands.slice(1)) @@ -790,26 +1075,44 @@ class WebpackCLI { await outputVersion(optionsForVersion, program); } - if (isKnownCommand(operand)) { - await loadCommandByName(operand, true); - } else { - logger.error(`Unknown command '${operand}'`); + let commandToRun = operand; + let commandOperands = operands.slice(1); - const found = knownCommands.find((commandOptions) => distance(operand, getCommandName(commandOptions.name)) < 3); + if (isKnownCommand(commandToRun)) { + await loadCommandByName(commandToRun, true); + } else { + let isEntrySyntax = true; - if (found) { - logger.error( - `Did you mean '${getCommandName(found.name)}' (alias '${ - Array.isArray(found.alias) ? found.alias.join(', ') : found.alias - }')?`, - ); + try { + await fs.promises.access(operand, fs.constants.F_OK); + } catch (error) { + isEntrySyntax = false; } - logger.error("Run 'webpack --help' to see available commands and options"); - process.exit(2); + if (isEntrySyntax) { + commandToRun = defaultCommandToRun; + commandOperands = operands; + + await loadCommandByName(commandToRun); + } else { + logger.error(`Unknown command or entry '${operand}'`); + + const found = knownCommands.find((commandOptions) => distance(operand, getCommandName(commandOptions.name)) < 3); + + if (found) { + logger.error( + `Did you mean '${getCommandName(found.name)}' (alias '${ + Array.isArray(found.alias) ? found.alias.join(', ') : found.alias + }')?`, + ); + } + + logger.error("Run 'webpack --help' to see available commands and options"); + process.exit(2); + } } - await this.program.parseAsync([operand, ...operands.slice(1), ...unknown], { from: 'user' }); + await this.program.parseAsync([commandToRun, ...commandOperands, ...unknown], { from: 'user' }); }); await this.program.parseAsync(args, parseOptions); @@ -818,11 +1121,11 @@ class WebpackCLI { async resolveConfig(options) { const loadConfig = async (configPath) => { const ext = path.extname(configPath); - const interpreted = Object.keys(jsVariants).find((variant) => variant === ext); + const interpreted = Object.keys(interpret.jsVariants).find((variant) => variant === ext); if (interpreted) { try { - rechoir.prepare(extensions, configPath); + rechoir.prepare(interpret.extensions, configPath); } catch (error) { if (error.failures) { logger.error(`Unable load '${configPath}'`); @@ -868,7 +1171,7 @@ class WebpackCLI { throw error; } } catch (error) { - logger.error(`Failed to load '${configPath}'`); + logger.error(`Failed to load '${configPath}' config`); logger.error(error); process.exit(2); } @@ -916,18 +1219,7 @@ class WebpackCLI { if (options.config && options.config.length > 0) { const evaluatedConfigs = await Promise.all( - options.config.map(async (value) => { - const configPath = path.resolve(value); - - if (!existsSync(configPath)) { - logger.error(`The specified config file doesn't exist in '${configPath}'`); - process.exit(2); - } - - const loadedConfig = await loadConfig(configPath); - - return evaluateConfig(loadedConfig, options.argv || {}); - }), + options.config.map(async (value) => evaluateConfig(await loadConfig(path.resolve(value)), options.argv || {})), ); config.options = []; @@ -950,10 +1242,10 @@ class WebpackCLI { const defaultConfigFiles = ['webpack.config', '.webpack/webpack.config', '.webpack/webpackfile'] .map((filename) => // Since .cjs is not available on interpret side add it manually to default config extension list - [...Object.keys(extensions), '.cjs'].map((ext) => ({ + [...Object.keys(interpret.extensions), '.cjs'].map((ext) => ({ path: path.resolve(filename + ext), ext: ext, - module: extensions[ext], + module: interpret.extensions[ext], })), ) .reduce((accumulator, currentValue) => accumulator.concat(currentValue), []); @@ -961,10 +1253,14 @@ class WebpackCLI { let foundDefaultConfigFile; for (const defaultConfigFile of defaultConfigFiles) { - if (existsSync(defaultConfigFile.path)) { - foundDefaultConfigFile = defaultConfigFile; - break; + try { + await fs.promises.access(defaultConfigFile.path, fs.constants.F_OK); + } catch (error) { + continue; } + + foundDefaultConfigFile = defaultConfigFile; + break; } if (foundDefaultConfigFile) { @@ -1011,6 +1307,8 @@ class WebpackCLI { } if (options.merge) { + const { merge } = require('webpack-merge'); + // we can only merge when there are multiple configurations // either by passing multiple configs by flags or passing a // single config exporting an array @@ -1057,34 +1355,33 @@ class WebpackCLI { process.exit(2); } - if (Object.keys(options).length === 0 && !process.env.NODE_ENV) { - return config; - } - - if (cli) { + if (this.webpack.cli) { const processArguments = (configOptions) => { - const coreFlagMap = flags + const args = this.getBuiltInOptions() .filter((flag) => flag.group === 'core') .reduce((accumulator, flag) => { accumulator[flag.name] = flag; return accumulator; }, {}); - const CLIoptions = Object.keys(options).reduce((accumulator, name) => { + + const values = Object.keys(options).reduce((accumulator, name) => { + if (name === 'argv') { + return accumulator; + } + const kebabName = toKebabCase(name); - if (coreFlagMap[kebabName]) { + if (args[kebabName]) { accumulator[kebabName] = options[name]; } return accumulator; }, {}); - const problems = cli.processArguments(coreFlagMap, configOptions, CLIoptions); + + const problems = this.webpack.cli.processArguments(args, configOptions, values); if (problems) { - const capitalizeFirstLetter = (string) => { - return string.charAt(0).toUpperCase() + string.slice(1); - }; const groupBy = (xs, key) => { return xs.reduce((rv, x) => { (rv[x[key]] = rv[x[key]] || []).push(x); @@ -1214,7 +1511,7 @@ class WebpackCLI { // Apply `stats` and `stats.colors` options const applyStatsColors = (configOptions) => { // TODO remove after drop webpack@4 - const statsForWebpack4 = webpack.Stats && webpack.Stats.presetToOptions; + const statsForWebpack4 = this.webpack.Stats && this.webpack.Stats.presetToOptions; if (statsForWebpack4) { if (typeof configOptions.stats === 'undefined') { @@ -1232,7 +1529,7 @@ class WebpackCLI { return configOptions; } - configOptions.stats = webpack.Stats.presetToOptions(configOptions.stats); + configOptions.stats = this.webpack.Stats.presetToOptions(configOptions.stats); } } else { if (typeof configOptions.stats === 'undefined') { @@ -1309,7 +1606,7 @@ class WebpackCLI { const isValidationError = (error) => { // https://github.com/webpack/webpack/blob/master/lib/index.js#L267 // https://github.com/webpack/webpack/blob/v4.44.2/lib/webpack.js#L90 - const ValidationError = webpack.ValidationError || webpack.WebpackOptionsValidationError; + const ValidationError = this.webpack.ValidationError || this.webpack.WebpackOptionsValidationError; return error instanceof ValidationError; }; @@ -1322,7 +1619,7 @@ class WebpackCLI { let compiler; try { - compiler = webpack( + compiler = this.webpack( config.options, callback ? (error, stats) => { @@ -1353,7 +1650,7 @@ class WebpackCLI { return compiler; } - async bundleCommand(options) { + async buildCommand(options) { let compiler; const callback = (error, stats) => { @@ -1377,7 +1674,7 @@ class WebpackCLI { : undefined; // TODO webpack@4 doesn't support `{ children: [{ colors: true }, { colors: true }] }` for stats - const statsForWebpack4 = webpack.Stats && webpack.Stats.presetToOptions; + const statsForWebpack4 = this.webpack.Stats && this.webpack.Stats.presetToOptions; if (compiler.compilers && statsForWebpack4) { statsOptions.colors = statsOptions.children.some((child) => child.colors); @@ -1399,7 +1696,7 @@ class WebpackCLI { } else { createJsonStringifyStream(stats.toJson(statsOptions)) .on('error', handleWriteError) - .pipe(createWriteStream(options.json)) + .pipe(fs.createWriteStream(options.json)) .on('error', handleWriteError) // Use stderr to logging .on('close', () => diff --git a/test/build/basic/basic.test.js b/test/build/basic/basic.test.js index a758c3b523c..01481187f45 100644 --- a/test/build/basic/basic.test.js +++ b/test/build/basic/basic.test.js @@ -3,7 +3,63 @@ const { run } = require('../../utils/test-utils'); describe('bundle command', () => { - it('should work', async () => { + it('should work without command (default command)', async () => { + const { exitCode, stderr, stdout } = run(__dirname, [], false); + + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toBeTruthy(); + }); + + it('should work without command and options (default command)', async () => { + const { exitCode, stderr, stdout } = run(__dirname, ['--mode', 'development'], false); + + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toBeTruthy(); + }); + + it('should work with multiple entries syntax without command (default command)', async () => { + const { exitCode, stderr, stdout } = run(__dirname, ['./src/index.js', './src/other.js'], false); + + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toBeTruthy(); + }); + + it('should work with multiple entries syntax without command with options (default command)', async () => { + const { exitCode, stderr, stdout } = run(__dirname, ['./src/index.js', './src/other.js', '--mode', 'development'], false); + + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toBeTruthy(); + }); + + it('should work with multiple entries syntax without command with options #2 (default command)', async () => { + const { exitCode, stderr, stdout } = run(__dirname, ['--mode', 'development', './src/index.js', './src/other.js'], false); + + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toBeTruthy(); + }); + + it('should work with multiple entries syntax without command with options #3 (default command)', async () => { + const { exitCode, stderr, stdout } = run(__dirname, ['./src/index.js', './src/other.js', '--entry', './src/again.js'], false); + + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toBeTruthy(); + }); + + it('should work with and override entries from the configuration', async () => { + const { exitCode, stderr, stdout } = run(__dirname, ['./src/index.js', './src/other.js', '--config', './entry.config.js'], false); + + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toBeTruthy(); + }); + + it('should work with the "build" alias', async () => { const { exitCode, stderr, stdout } = run(__dirname, ['build'], false); expect(exitCode).toBe(0); @@ -11,6 +67,14 @@ describe('bundle command', () => { expect(stdout).toBeTruthy(); }); + it('should work with "bundle" alias', async () => { + const { exitCode, stderr, stdout } = run(__dirname, ['bundle'], false); + + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toBeTruthy(); + }); + it('should work with the "b" alias', async () => { const { exitCode, stderr, stdout } = run(__dirname, ['b'], false); @@ -19,40 +83,60 @@ describe('bundle command', () => { expect(stdout).toBeTruthy(); }); - it('should work with "bundle" alias', async () => { - const { exitCode, stderr, stdout } = run(__dirname, ['bundle'], false); + it('should work with entries syntax using the "build" alias', async () => { + const { exitCode, stderr, stdout } = run(__dirname, ['build', './src/index.js'], false); expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); expect(stdout).toBeTruthy(); }); - it('should log error and suggest right name on the "buil" command', async () => { - const { exitCode, stderr, stdout } = run(__dirname, ['buil'], false); + it('should work with entries syntax using the "bundle" alias', async () => { + const { exitCode, stderr, stdout } = run(__dirname, ['bundle', './src/index.js'], false); - expect(exitCode).toBe(2); - expect(stderr).toContain("Unknown command 'buil'"); - expect(stderr).toContain("Did you mean 'build' (alias 'bundle, b')?"); - expect(stderr).toContain("Run 'webpack --help' to see available commands and options"); - expect(stdout).toBeFalsy(); + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toBeTruthy(); }); - it('should log error with multi commands', async () => { - const { exitCode, stderr, stdout } = run(__dirname, ['bundle', 'info'], false); + it('should work with entries syntax using the "b" alias', async () => { + const { exitCode, stderr, stdout } = run(__dirname, ['b', './src/index.js'], false); - expect(exitCode).toBe(2); - expect(stderr).toContain('Running multiple commands at the same time is not possible'); - expect(stderr).toContain("Found commands: 'build', 'info'"); - expect(stderr).toContain("Run 'webpack --help' to see available commands and options"); - expect(stdout).toBeFalsy(); + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toBeTruthy(); + }); + + it('should work with multiple entries syntax using the "build" alias', async () => { + const { exitCode, stderr, stdout } = run(__dirname, ['build', './src/index.js', './src/other.js'], false); + + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toBeTruthy(); + }); + + it('should work with multiple entries syntax using the "build" alias and options', async () => { + const { exitCode, stderr, stdout } = run(__dirname, ['build', './src/index.js', './src/other.js', '--mode', 'development'], false); + + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toBeTruthy(); }); - it('should log error with multi commands', async () => { - const { exitCode, stderr, stdout } = run(__dirname, ['b', 'i'], false); + it('should work with multiple entries syntax using the "build" alias and options', async () => { + const { exitCode, stderr, stdout } = run(__dirname, ['build', '--mode', 'development', './src/index.js', './src/other.js'], false); + + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toBeTruthy(); + }); + + it('should log error and suggest right name on the "buil" command', async () => { + const { exitCode, stderr, stdout } = run(__dirname, ['buil'], false); expect(exitCode).toBe(2); - expect(stderr).toContain('Running multiple commands at the same time is not possible'); - expect(stderr).toContain("Found commands: 'build', 'i'"); + expect(stderr).toContain("Unknown command or entry 'buil'"); + expect(stderr).toContain("Did you mean 'build' (alias 'bundle, b')?"); expect(stderr).toContain("Run 'webpack --help' to see available commands and options"); expect(stdout).toBeFalsy(); }); diff --git a/test/build/basic/entry.config.js b/test/build/basic/entry.config.js new file mode 100644 index 00000000000..431945f5225 --- /dev/null +++ b/test/build/basic/entry.config.js @@ -0,0 +1,4 @@ +module.exports = { + mode: 'development', + entry: './src/entry.js', +}; diff --git a/test/build/basic/src/again.js b/test/build/basic/src/again.js new file mode 100644 index 00000000000..eec159b09dc --- /dev/null +++ b/test/build/basic/src/again.js @@ -0,0 +1 @@ +console.log('again'); diff --git a/test/build/basic/src/entry.js b/test/build/basic/src/entry.js new file mode 100644 index 00000000000..6daf0ddddd1 --- /dev/null +++ b/test/build/basic/src/entry.js @@ -0,0 +1 @@ +console.log('CONFIG'); diff --git a/test/build/basic/src/other.js b/test/build/basic/src/other.js new file mode 100644 index 00000000000..6be02374db1 --- /dev/null +++ b/test/build/basic/src/other.js @@ -0,0 +1 @@ +console.log('hello world'); diff --git a/test/config/absent/config-absent.test.js b/test/config/absent/config-absent.test.js index 2a10305273c..1e22b4a67a0 100644 --- a/test/config/absent/config-absent.test.js +++ b/test/config/absent/config-absent.test.js @@ -1,16 +1,16 @@ 'use strict'; -const { resolve } = require('path'); +const path = require('path'); const { run } = require('../../utils/test-utils'); describe('Config:', () => { it('supplied config file is absent', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['-c', resolve(__dirname, 'webpack.config.js')], false); + const { exitCode, stderr, stdout } = run(__dirname, ['-c', path.resolve(__dirname, 'webpack.config.js')], false); // should throw with correct exit code expect(exitCode).toBe(2); // Should contain the correct error message - expect(stderr).toContain(`The specified config file doesn't exist in '${resolve(__dirname, 'webpack.config.js')}'`); + expect(stderr).toContain(`Failed to load '${path.resolve(__dirname, 'webpack.config.js')}' config`); expect(stdout).toBeFalsy(); }); }); diff --git a/test/config/invalid-path/invalid-path.test.js b/test/config/invalid-path/invalid-path.test.js index b571740a71f..fe94a8826d9 100644 --- a/test/config/invalid-path/invalid-path.test.js +++ b/test/config/invalid-path/invalid-path.test.js @@ -1,13 +1,13 @@ 'use strict'; -const { resolve } = require('path'); +const path = require('path'); const { run } = require('../../utils/test-utils'); describe('basic config file', () => { it('is able to understand and parse a very basic configuration file', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['-c', resolve(__dirname, 'invalid-webpack.config.js')], false); + const { exitCode, stderr, stdout } = run(__dirname, ['-c', path.resolve(__dirname, 'invalid-webpack.config.js')], false); expect(exitCode).toBe(2); - expect(stderr).toContain(`The specified config file doesn't exist in '${resolve(__dirname, 'invalid-webpack.config.js')}'`); + expect(stderr).toContain(`Failed to load '${path.resolve(__dirname, 'invalid-webpack.config.js')}' config`); expect(stdout).toBeFalsy(); }); }); diff --git a/test/configtest/with-config-path/with-config-path.test.js b/test/configtest/with-config-path/with-config-path.test.js index 2e4775868c0..ca2ae90524a 100644 --- a/test/configtest/with-config-path/with-config-path.test.js +++ b/test/configtest/with-config-path/with-config-path.test.js @@ -44,7 +44,7 @@ describe("'configtest' command with the configuration path option", () => { const { exitCode, stderr, stdout } = run(__dirname, ['configtest', './a.js'], false); expect(exitCode).toBe(2); - expect(stderr).toContain(`The specified config file doesn't exist`); + expect(stderr).toContain(`Failed to load '${path.resolve(__dirname, './a.js')}' config`); expect(stdout).toBeFalsy(); }); }); diff --git a/test/core-flags/experiments-flag.test.js b/test/core-flags/experiments-flag.test.js index b7554dff33e..f0bf72803eb 100644 --- a/test/core-flags/experiments-flag.test.js +++ b/test/core-flags/experiments-flag.test.js @@ -1,9 +1,10 @@ 'use strict'; const { run, hyphenToUpperCase } = require('../utils/test-utils'); -const { flags } = require('../../packages/webpack-cli/lib/utils/cli-flags'); +const CLI = require('../../packages/webpack-cli/lib/index'); -const experimentsFlags = flags.filter(({ name }) => name.startsWith('experiments-')); +const cli = new CLI(); +const experimentsFlags = cli.getBuiltInOptions().filter(({ name }) => name.startsWith('experiments-')); describe('experiments option related flag', () => { experimentsFlags.forEach((flag) => { diff --git a/test/core-flags/externals-flags.test.js b/test/core-flags/externals-flags.test.js index f402a194691..66b2e549c2d 100644 --- a/test/core-flags/externals-flags.test.js +++ b/test/core-flags/externals-flags.test.js @@ -1,9 +1,10 @@ 'use strict'; const { run, hyphenToUpperCase } = require('../utils/test-utils'); -const { flags } = require('../../packages/webpack-cli/lib/utils/cli-flags'); +const CLI = require('../../packages/webpack-cli/lib/index'); -const externalsPresetsFlags = flags.filter(({ name }) => name.startsWith('externals-presets-')); +const cli = new CLI(); +const externalsPresetsFlags = cli.getBuiltInOptions().filter(({ name }) => name.startsWith('externals-presets-')); describe('externals related flag', () => { it('should set externals properly', () => { diff --git a/test/core-flags/module-flags.test.js b/test/core-flags/module-flags.test.js index bc7ccd1faa6..5a3759573fe 100644 --- a/test/core-flags/module-flags.test.js +++ b/test/core-flags/module-flags.test.js @@ -1,9 +1,10 @@ 'use strict'; const { run, hyphenToUpperCase } = require('../utils/test-utils'); -const { flags } = require('../../packages/webpack-cli/lib/utils/cli-flags'); +const CLI = require('../../packages/webpack-cli/lib/index'); -const moduleFlags = flags.filter(({ name }) => name.startsWith('module-')); +const cli = new CLI(); +const moduleFlags = cli.getBuiltInOptions().filter(({ name }) => name.startsWith('module-')); describe('module config related flag', () => { moduleFlags.forEach((flag) => { diff --git a/test/core-flags/optimization-flags.test.js b/test/core-flags/optimization-flags.test.js index 72cd235c357..079f95929ab 100644 --- a/test/core-flags/optimization-flags.test.js +++ b/test/core-flags/optimization-flags.test.js @@ -1,9 +1,10 @@ 'use strict'; const { run, hyphenToUpperCase } = require('../utils/test-utils'); -const { flags } = require('../../packages/webpack-cli/lib/utils/cli-flags'); +const CLI = require('../../packages/webpack-cli/lib/index'); -const optimizationFlags = flags.filter(({ name }) => name.startsWith('optimization-')); +const cli = new CLI(); +const optimizationFlags = cli.getBuiltInOptions().filter(({ name }) => name.startsWith('optimization-')); describe('optimization config related flag', () => { optimizationFlags.forEach((flag) => { diff --git a/test/core-flags/output-flags.test.js b/test/core-flags/output-flags.test.js index fb08268a5a1..3829a5e3a21 100644 --- a/test/core-flags/output-flags.test.js +++ b/test/core-flags/output-flags.test.js @@ -1,9 +1,10 @@ 'use strict'; const { run, hyphenToUpperCase } = require('../utils/test-utils'); -const { flags } = require('../../packages/webpack-cli/lib/utils/cli-flags'); +const CLI = require('../../packages/webpack-cli/lib/index'); -const outputFlags = flags.filter(({ name }) => name.startsWith('output-')); +const cli = new CLI(); +const outputFlags = cli.getBuiltInOptions().filter(({ name }) => name.startsWith('output-')); describe('output config related flag', () => { outputFlags.forEach((flag) => { diff --git a/test/core-flags/performance-flags.test.js b/test/core-flags/performance-flags.test.js index f13d1ca0221..9d113fc7f22 100644 --- a/test/core-flags/performance-flags.test.js +++ b/test/core-flags/performance-flags.test.js @@ -1,9 +1,10 @@ 'use strict'; const { run, hyphenToUpperCase } = require('../utils/test-utils'); -const { flags } = require('../../packages/webpack-cli/lib/utils/cli-flags'); +const CLI = require('../../packages/webpack-cli/lib/index'); -const performanceFlags = flags.filter(({ name }) => name.startsWith('performance-')); +const cli = new CLI(); +const performanceFlags = cli.getBuiltInOptions().filter(({ name }) => name.startsWith('performance-')); describe('module config related flag', () => { it(`should config --performance option correctly`, () => { diff --git a/test/core-flags/resolve-flags.test.js b/test/core-flags/resolve-flags.test.js index e2c069ff02c..6b0318fcbf6 100644 --- a/test/core-flags/resolve-flags.test.js +++ b/test/core-flags/resolve-flags.test.js @@ -1,9 +1,10 @@ 'use strict'; const { run, hyphenToUpperCase } = require('../utils/test-utils'); -const { flags } = require('../../packages/webpack-cli/lib/utils/cli-flags'); +const CLI = require('../../packages/webpack-cli/lib/index'); -const resolveFlags = flags.filter(({ name }) => name.startsWith('resolve')); +const cli = new CLI(); +const resolveFlags = cli.getBuiltInOptions().filter(({ name }) => name.startsWith('resolve')); describe('resolve config related flags', () => { resolveFlags.forEach((flag) => { diff --git a/test/core-flags/snapshot-flags.test.js b/test/core-flags/snapshot-flags.test.js index 5860127cb3b..9cc9077db49 100644 --- a/test/core-flags/snapshot-flags.test.js +++ b/test/core-flags/snapshot-flags.test.js @@ -1,9 +1,10 @@ 'use strict'; const { run, hyphenToUpperCase } = require('../utils/test-utils'); -const { flags } = require('../../packages/webpack-cli/lib/utils/cli-flags'); +const CLI = require('../../packages/webpack-cli/lib/index'); -const snapshotFlags = flags.filter(({ name }) => name.startsWith('snapshot')); +const cli = new CLI(); +const snapshotFlags = cli.getBuiltInOptions().filter(({ name }) => name.startsWith('snapshot')); describe('snapshot config related flags', () => { snapshotFlags.forEach((flag) => { diff --git a/test/core-flags/stats-flags.test.js b/test/core-flags/stats-flags.test.js index 3dccbbea5b5..77d7ff11edd 100644 --- a/test/core-flags/stats-flags.test.js +++ b/test/core-flags/stats-flags.test.js @@ -1,9 +1,10 @@ 'use strict'; const { run, hyphenToUpperCase } = require('../utils/test-utils'); -const { flags } = require('../../packages/webpack-cli/lib/utils/cli-flags'); +const CLI = require('../../packages/webpack-cli/lib/index'); -const statsFlags = flags.filter(({ name }) => name.startsWith('stats-')); +const cli = new CLI(); +const statsFlags = cli.getBuiltInOptions().filter(({ name }) => name.startsWith('stats-')); describe('stats config related flag', () => { statsFlags.forEach((flag) => { diff --git a/test/core-flags/watch-flags.test.js b/test/core-flags/watch-flags.test.js index ddb47635f17..34656cccf7d 100644 --- a/test/core-flags/watch-flags.test.js +++ b/test/core-flags/watch-flags.test.js @@ -1,9 +1,10 @@ 'use strict'; const { run, hyphenToUpperCase } = require('../utils/test-utils'); -const { flags } = require('../../packages/webpack-cli/lib/utils/cli-flags'); +const CLI = require('../../packages/webpack-cli/lib/index'); -const watchFlags = flags.filter(({ name }) => name.startsWith('watch')); +const cli = new CLI(); +const watchFlags = cli.getBuiltInOptions().filter(({ name }) => name.startsWith('watch')); describe('watch config related flag', () => { watchFlags.forEach((flag) => { diff --git a/test/core-flags/webpack.test.config.js b/test/core-flags/webpack.test.config.js deleted file mode 100644 index cd24476ff4c..00000000000 --- a/test/core-flags/webpack.test.config.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = { mode: 'development' }; diff --git a/test/help/help.test.js b/test/help/help.test.js index 9b40070f5ab..4f1b703ede1 100644 --- a/test/help/help.test.js +++ b/test/help/help.test.js @@ -8,111 +8,124 @@ const helpDefaultHeader = 'The build tool for modern web applications.'; describe('help', () => { it('should show help information using the "--help" option', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['--help'], false); + const { exitCode, stderr, stdout } = run(__dirname, ['--help']); expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); - expect(stdout).toContain('webpack [options]'); - expect(stdout).toContain(helpDefaultHeader); - expect(stdout).toContain('Options:'); - expect(stdout).toContain('--merge'); // minimum - expect(stdout).not.toContain('--cache-type'); // verbose - expect(stdout).toContain('Global options:'); - expect(stdout).toContain('Commands:'); - expect(stdout.match(/build\|bundle\|b/g)).toHaveLength(1); - expect(stdout.match(/watch\|w/g)).toHaveLength(1); - expect(stdout.match(/version\|v/g)).toHaveLength(1); - expect(stdout.match(/help\|h/g)).toHaveLength(1); - expect(stdout.match(/serve\|s/g)).toHaveLength(1); - expect(stdout.match(/info\|i/g)).toHaveLength(1); - expect(stdout.match(/init\|c/g)).toHaveLength(1); - expect(stdout.match(/loader\|l/g)).toHaveLength(1); - expect(stdout.match(/plugin\|p/g)).toHaveLength(1); - expect(stdout.match(/migrate\|m/g)).toHaveLength(1); - expect(stdout.match(/configtest\|t/g)).toHaveLength(1); - expect(stdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); - expect(stdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); - // TODO buggy on windows - // expect(coloretteEnabled ? stripAnsi(stdout) : stdout).toContain('Made with ♥ by the webpack team.'); + + const pureStdout = stripAnsi(stdout); + + expect(pureStdout).toContain('webpack [entries...] [options]'); + expect(pureStdout).toContain('webpack [command] [options]'); + expect(pureStdout).toContain(helpDefaultHeader); + expect(pureStdout).toContain('Options:'); + expect(pureStdout).toContain('--merge'); // minimum + expect(pureStdout).not.toContain('--cache-type'); // verbose + expect(pureStdout).toContain('Global options:'); + expect(pureStdout).toContain('Commands:'); + expect(pureStdout.match(/build\|bundle\|b/g)).toHaveLength(1); + expect(pureStdout.match(/watch\|w/g)).toHaveLength(1); + expect(pureStdout.match(/version\|v/g)).toHaveLength(1); + expect(pureStdout.match(/help\|h/g)).toHaveLength(1); + expect(pureStdout.match(/serve\|s/g)).toHaveLength(1); + expect(pureStdout.match(/info\|i/g)).toHaveLength(1); + expect(pureStdout.match(/init\|c/g)).toHaveLength(1); + expect(pureStdout.match(/loader\|l/g)).toHaveLength(1); + expect(pureStdout.match(/plugin\|p/g)).toHaveLength(1); + expect(pureStdout.match(/migrate\|m/g)).toHaveLength(1); + expect(pureStdout.match(/configtest\|t/g)).toHaveLength(1); + expect(pureStdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); + expect(pureStdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); + expect(pureStdout).toContain('Made with ♥ by the webpack team.'); }); it.skip('should show help information using the "--help" option with the "verbose" value', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['--help', 'verbose'], false); + const { exitCode, stderr, stdout } = run(__dirname, ['--help', 'verbose']); expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); - expect(stdout).toContain('webpack [options]'); - expect(stdout).toContain(helpDefaultHeader); - expect(stdout).toContain('Options:'); - expect(stdout).toContain('--merge'); // minimum + + const pureStdout = stripAnsi(stdout); + + expect(pureStdout).toContain('webpack [entries...] [options]'); + expect(pureStdout).toContain('webpack [command] [options]'); + expect(pureStdout).toContain(helpDefaultHeader); + expect(pureStdout).toContain('Options:'); + expect(pureStdout).toContain('--merge'); // minimum if (isWebpack5) { - expect(stdout).toContain('--cache-type'); // verbose + expect(pureStdout).toContain('--cache-type'); // verbose } - expect(stdout).toContain('Global options:'); - expect(stdout).toContain('Commands:'); - expect(stdout.match(/build\|bundle\|b/g)).toHaveLength(1); - expect(stdout.match(/watch\|w/g)).toHaveLength(1); - expect(stdout.match(/version\|v/g)).toHaveLength(1); - expect(stdout.match(/help\|h/g)).toHaveLength(1); - expect(stdout.match(/serve\|s/g)).toHaveLength(1); - expect(stdout.match(/info\|i/g)).toHaveLength(1); - expect(stdout.match(/init\|c/g)).toHaveLength(1); - expect(stdout.match(/loader\|l/g)).toHaveLength(1); - expect(stdout.match(/plugin\|p/g)).toHaveLength(1); - expect(stdout.match(/migrate\|m/g)).toHaveLength(1); - expect(stdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); - expect(stdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); - expect(coloretteEnabled ? stripAnsi(stdout) : stdout).toContain('Made with ♥ by the webpack team.'); + expect(pureStdout).toContain('Global options:'); + expect(pureStdout).toContain('Commands:'); + expect(pureStdout.match(/build\|bundle\|b/g)).toHaveLength(1); + expect(pureStdout.match(/watch\|w/g)).toHaveLength(1); + expect(pureStdout.match(/version\|v/g)).toHaveLength(1); + expect(pureStdout.match(/help\|h/g)).toHaveLength(1); + expect(pureStdout.match(/serve\|s/g)).toHaveLength(1); + expect(pureStdout.match(/info\|i/g)).toHaveLength(1); + expect(pureStdout.match(/init\|c/g)).toHaveLength(1); + expect(pureStdout.match(/loader\|l/g)).toHaveLength(1); + expect(pureStdout.match(/plugin\|p/g)).toHaveLength(1); + expect(pureStdout.match(/migrate\|m/g)).toHaveLength(1); + expect(pureStdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); + expect(pureStdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); + expect(pureStdout).toContain('Made with ♥ by the webpack team.'); }); it.skip('should show help information using the "--help" option with the "verbose" value #2', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['--help=verbose'], false); + const { exitCode, stderr, stdout } = run(__dirname, ['--help=verbose']); expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); - expect(stdout).toContain('webpack [options]'); - expect(stdout).toContain(helpDefaultHeader); - expect(stdout).toContain('Options:'); - expect(stdout).toContain('--merge'); // minimum + + const pureStdout = stripAnsi(stdout); + + expect(pureStdout).toContain('webpack [entries...] [options]'); + expect(pureStdout).toContain('webpack [command] [options]'); + expect(pureStdout).toContain(helpDefaultHeader); + expect(pureStdout).toContain('Options:'); + expect(pureStdout).toContain('--merge'); // minimum if (isWebpack5) { - expect(stdout).toContain('--cache-type'); // verbose + expect(pureStdout).toContain('--cache-type'); // verbose } - expect(stdout).toContain('Global options:'); - expect(stdout).toContain('Commands:'); - expect(stdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); - expect(stdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); + expect(pureStdout).toContain('Global options:'); + expect(pureStdout).toContain('Commands:'); + expect(pureStdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); + expect(pureStdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); expect(coloretteEnabled ? stripAnsi(stdout) : stdout).toContain('Made with ♥ by the webpack team.'); }); it('should show help information using command syntax', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['help'], false); + const { exitCode, stderr, stdout } = run(__dirname, ['help']); expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); - expect(stdout).toContain('webpack [options]'); - expect(stdout).toContain(helpDefaultHeader); - expect(stdout).toContain('Options:'); - expect(stdout).toContain('--merge'); // minimum - expect(stdout).not.toContain('--cache-type'); // verbose - expect(stdout).toContain('Global options:'); - expect(stdout).toContain('Commands:'); - expect(stdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); - expect(stdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); + + const pureStdout = stripAnsi(stdout); + + expect(pureStdout).toContain('webpack [entries...] [options]'); + expect(pureStdout).toContain('webpack [command] [options]'); + expect(pureStdout).toContain(helpDefaultHeader); + expect(pureStdout).toContain('Options:'); + expect(pureStdout).toContain('--merge'); // minimum + expect(pureStdout).not.toContain('--cache-type'); // verbose + expect(pureStdout).toContain('Global options:'); + expect(pureStdout).toContain('Commands:'); + expect(pureStdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); + expect(pureStdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); // TODO buggy on windows // expect(coloretteEnabled ? stripAnsi(stdout) : stdout).toContain('Made with ♥ by the webpack team.'); }); it('should show the same information using the "--help" option and command syntax', () => { - const { exitCode: exitCodeFromOption, stderr: stderrFromOption, stdout: stdoutFromOption } = run(__dirname, ['--help'], false); - const { exitCode: exitCodeFromCommandSyntax, stderr: stderrFromCommandSyntax, stdout: stdoutFromCommandSyntax } = run( - __dirname, - ['help'], - false, - ); + const { exitCode: exitCodeFromOption, stderr: stderrFromOption, stdout: stdoutFromOption } = run(__dirname, ['--help']); + const { exitCode: exitCodeFromCommandSyntax, stderr: stderrFromCommandSyntax, stdout: stdoutFromCommandSyntax } = run(__dirname, [ + 'help', + ]); expect(exitCodeFromOption).toBe(0); expect(exitCodeFromCommandSyntax).toBe(0); @@ -122,39 +135,47 @@ describe('help', () => { }); it('should show help information and respect the "--color" flag using the "--help" option', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['--help', '--color'], false); + const { exitCode, stderr, stdout } = run(__dirname, ['--help', '--color']); expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); - expect(stdout).toContain('webpack [options]'); - expect(stdout).toContain(helpDefaultHeader); - expect(stdout).toContain('Options:'); - expect(stdout).toContain('--merge'); // minimum - expect(stdout).not.toContain('--cache-type'); // verbose - expect(stdout).toContain('Global options:'); - expect(stdout).toContain('Commands:'); - expect(stdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); - expect(stdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); - expect(stdout).toContain(coloretteEnabled ? bold('Made with ♥ by the webpack team') : 'Made with ♥ by the webpack team'); + + const pureStdout = stripAnsi(stdout); + + expect(pureStdout).toContain('webpack [entries...] [options]'); + expect(pureStdout).toContain('webpack [command] [options]'); + expect(pureStdout).toContain(helpDefaultHeader); + expect(pureStdout).toContain('Options:'); + expect(pureStdout).toContain('--merge'); // minimum + expect(pureStdout).not.toContain('--cache-type'); // verbose + expect(pureStdout).toContain('Global options:'); + expect(pureStdout).toContain('Commands:'); + expect(pureStdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); + expect(pureStdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); + expect(pureStdout).toContain(coloretteEnabled ? bold('Made with ♥ by the webpack team') : 'Made with ♥ by the webpack team'); }); it('should show help information and respect the "--no-color" flag using the "--help" option', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['--help', '--no-color'], false); + const { exitCode, stderr, stdout } = run(__dirname, ['--help', '--no-color']); expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); - expect(stdout).toContain('webpack [options]'); - expect(stdout).toContain(helpDefaultHeader); - expect(stdout).toContain('Options:'); - expect(stdout).toContain('--merge'); // minimum - expect(stdout).not.toContain('--cache-type'); // verbose - expect(stdout).toContain('Global options:'); - expect(stdout).toContain('Commands:'); - expect(stdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); - expect(stdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); + + const pureStdout = stripAnsi(stdout); + + expect(pureStdout).toContain('webpack [entries...] [options]'); + expect(pureStdout).toContain('webpack [command] [options]'); + expect(pureStdout).toContain(helpDefaultHeader); + expect(pureStdout).toContain('Options:'); + expect(pureStdout).toContain('--merge'); // minimum + expect(pureStdout).not.toContain('--cache-type'); // verbose + expect(pureStdout).toContain('Global options:'); + expect(pureStdout).toContain('Commands:'); + expect(pureStdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); + expect(pureStdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); // TODO bug in tests // expect(stdout).not.toContain(bold('Made with ♥ by the webpack team')); - expect(stdout).toContain('Made with ♥ by the webpack team'); + expect(pureStdout).toContain('Made with ♥ by the webpack team'); }); const commands = [ @@ -181,7 +202,7 @@ describe('help', () => { commands.forEach((command) => { it(`should show help information for '${command}' command using the "--help" option`, () => { - const { exitCode, stderr, stdout } = run(__dirname, [command, '--help'], false); + const { exitCode, stderr, stdout } = run(__dirname, [command, '--help']); expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); @@ -189,7 +210,7 @@ describe('help', () => { }); it(`should show help information for '${command}' command using command syntax`, () => { - const { exitCode, stderr, stdout } = run(__dirname, ['help', command], false); + const { exitCode, stderr, stdout } = run(__dirname, ['help', command]); expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); @@ -197,7 +218,7 @@ describe('help', () => { }); it('should show help information and respect the "--color" flag using the "--help" option', () => { - const { exitCode, stderr, stdout } = run(__dirname, [command, '--help', '--color'], false); + const { exitCode, stderr, stdout } = run(__dirname, [command, '--help', '--color']); expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); @@ -206,7 +227,7 @@ describe('help', () => { }); it('should show help information and respect the "--no-color" flag using the "--help" option', () => { - const { exitCode, stderr, stdout } = run(__dirname, [command, '--help', '--no-color'], false); + const { exitCode, stderr, stdout } = run(__dirname, [command, '--help', '--no-color']); expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); @@ -218,145 +239,178 @@ describe('help', () => { }); it('should show help information with options for sub commands', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['info', '--help'], false); + const { exitCode, stderr, stdout } = run(__dirname, ['info', '--help']); expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); - expect(stdout).toContain('webpack info|i [options]'); - expect(stdout).toContain('Options:'); - expect(stdout).toContain('--output '); - expect(stdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); - expect(stdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); - expect(stdout).toContain('Made with ♥ by the webpack team'); + + const pureStdout = stripAnsi(stdout); + + expect(pureStdout).toContain('webpack info|i [options]'); + expect(pureStdout).toContain('Options:'); + expect(pureStdout).toContain('--output '); + expect(pureStdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); + expect(pureStdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); + expect(pureStdout).toContain('Made with ♥ by the webpack team'); }); it('should show help information and taking precedence when "--help" and "--version" option using together', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['--help', '--version'], false); + const { exitCode, stderr, stdout } = run(__dirname, ['--help', '--version']); expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); - expect(stdout).toContain('webpack [options]'); - expect(stdout).toContain(helpDefaultHeader); - expect(stdout).toContain('Options:'); - expect(stdout).toContain('--merge'); // minimum - expect(stdout).not.toContain('--cache-type'); // verbose - expect(stdout).toContain('Global options:'); - expect(stdout).toContain('Commands:'); - expect(stdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); - expect(stdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); + + const pureStdout = stripAnsi(stdout); + + expect(pureStdout).toContain('webpack [entries...] [options]'); + expect(pureStdout).toContain('webpack [command] [options]'); + expect(pureStdout).toContain(helpDefaultHeader); + expect(pureStdout).toContain('Options:'); + expect(pureStdout).toContain('--merge'); // minimum + expect(pureStdout).not.toContain('--cache-type'); // verbose + expect(pureStdout).toContain('Global options:'); + expect(pureStdout).toContain('Commands:'); + expect(pureStdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); + expect(pureStdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); // TODO buggy on windows // expect(coloretteEnabled ? stripAnsi(stdout) : stdout).toContain('Made with ♥ by the webpack team.'); }); it('should show help information using the "help --mode" option', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['help', '--mode'], false); + const { exitCode, stderr, stdout } = run(__dirname, ['help', '--mode']); expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); - expect(stdout).toContain('Usage: webpack --mode '); - expect(stdout).toContain('Description: Defines the mode to pass to webpack.'); - expect(stdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); - expect(stdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); + + const pureStdout = stripAnsi(stdout); + + expect(pureStdout).toContain('Usage: webpack --mode '); + expect(pureStdout).toContain('Description: Defines the mode to pass to webpack.'); + expect(pureStdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); + expect(pureStdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); }); it('should show help information using the "help --target" option', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['help', '--target'], false); + const { exitCode, stderr, stdout } = run(__dirname, ['help', '--target']); expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); + const pureStdout = stripAnsi(stdout); + if (isWebpack5) { - expect(stdout).toContain('Usage: webpack --target '); - expect(stdout).toContain('Short: webpack -t '); + expect(pureStdout).toContain('Usage: webpack --target '); + expect(pureStdout).toContain('Short: webpack -t '); } else { - expect(stdout).toContain('Usage: webpack --target '); - expect(stdout).toContain('Short: webpack -t '); + expect(pureStdout).toContain('Usage: webpack --target '); + expect(pureStdout).toContain('Short: webpack -t '); } - expect(stdout).toContain('Description: Sets the build target e.g. node.'); - expect(stdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); - expect(stdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); + expect(pureStdout).toContain('Description: Sets the build target e.g. node.'); + expect(pureStdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); + expect(pureStdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); }); it('should show help information using the "help --stats" option', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['help', '--stats'], false); + const { exitCode, stderr, stdout } = run(__dirname, ['help', '--stats']); expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); - expect(stdout).toContain('Usage: webpack --stats [value]'); - expect(stdout).toContain('Description: It instructs webpack on how to treat the stats e.g. verbose.'); - expect(stdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); - expect(stdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); + + const pureStdout = stripAnsi(stdout); + + expect(pureStdout).toContain('Usage: webpack --stats [value]'); + expect(pureStdout).toContain('Description: It instructs webpack on how to treat the stats e.g. verbose.'); + expect(pureStdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); + expect(pureStdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); }); it('should show help information using the "help --no-stats" option', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['help', '--no-stats'], false); + const { exitCode, stderr, stdout } = run(__dirname, ['help', '--no-stats']); expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); - expect(stdout).toContain('Usage: webpack --no-stats'); - expect(stdout).toContain('Description: Disable stats output.'); - expect(stdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); - expect(stdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); + + const pureStdout = stripAnsi(stdout); + + expect(pureStdout).toContain('Usage: webpack --no-stats'); + expect(pureStdout).toContain('Description: Disable stats output.'); + expect(pureStdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); + expect(pureStdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); }); it('should show help information using the "help --mode" option', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['help', '--mode'], false); + const { exitCode, stderr, stdout } = run(__dirname, ['help', '--mode']); expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); - expect(stdout).toContain('Usage: webpack --mode '); - expect(stdout).toContain('Description: Defines the mode to pass to webpack.'); - expect(stdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); - expect(stdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); + + const pureStdout = stripAnsi(stdout); + + expect(pureStdout).toContain('Usage: webpack --mode '); + expect(pureStdout).toContain('Description: Defines the mode to pass to webpack.'); + expect(pureStdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); + expect(pureStdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); }); it('should show help information using the "help serve --mode" option', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['help', 'serve', '--mode'], false); + const { exitCode, stderr, stdout } = run(__dirname, ['help', 'serve', '--mode']); expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); - expect(stdout).toContain('Usage: webpack serve --mode '); - expect(stdout).toContain('Description: Defines the mode to pass to webpack.'); - expect(stdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); - expect(stdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); + + const pureStdout = stripAnsi(stdout); + + expect(pureStdout).toContain('Usage: webpack serve --mode '); + expect(pureStdout).toContain('Description: Defines the mode to pass to webpack.'); + expect(pureStdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); + expect(pureStdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); }); it('should show help information using the "help --color" option', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['help', '--color'], false); + const { exitCode, stderr, stdout } = run(__dirname, ['help', '--color']); expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); - expect(stdout).toContain('Usage: webpack --color'); - expect(stdout).toContain('Description: Enable colors on console.'); - expect(stdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); - expect(stdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); + + const pureStdout = stripAnsi(stdout); + + expect(pureStdout).toContain('Usage: webpack --color'); + expect(pureStdout).toContain('Description: Enable colors on console.'); + expect(pureStdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); + expect(pureStdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); }); it('should show help information using the "help --no-color" option', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['help', '--no-color'], false); + const { exitCode, stderr, stdout } = run(__dirname, ['help', '--no-color']); expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); - expect(stdout).toContain('Usage: webpack --no-color'); - expect(stdout).toContain('Description: Disable colors on console.'); - expect(stdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); - expect(stdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); + + const pureStdout = stripAnsi(stdout); + + expect(pureStdout).toContain('Usage: webpack --no-color'); + expect(pureStdout).toContain('Description: Disable colors on console.'); + expect(pureStdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); + expect(pureStdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); }); it('should show help information using the "help serve --color" option', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['help', 'serve', '--color'], false); + const { exitCode, stderr, stdout } = run(__dirname, ['help', 'serve', '--color']); expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); - expect(stdout).toContain('Usage: webpack serve --color'); - expect(stdout).toContain('Description: Enable colors on console.'); - expect(stdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); - expect(stdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); + + const pureStdout = stripAnsi(stdout); + + expect(pureStdout).toContain('Usage: webpack serve --color'); + expect(pureStdout).toContain('Description: Enable colors on console.'); + expect(pureStdout).toContain("To see list of all supported commands and options run 'webpack --help=verbose'."); + expect(pureStdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); }); it('should show help information using the "help serve --no-color" option', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['help', 'serve', '--no-color'], false); + const { exitCode, stderr, stdout } = run(__dirname, ['help', 'serve', '--no-color']); expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); @@ -367,33 +421,39 @@ describe('help', () => { }); it('should show help information using the "help --version" option', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['help', '--version'], false); + const { exitCode, stderr, stdout } = run(__dirname, ['help', '--version']); expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); - expect(stdout).toContain('Usage: webpack --version'); - expect(stdout).toContain('Short: webpack -v'); - expect(stdout).toContain( + + const pureStdout = stripAnsi(stdout); + + expect(pureStdout).toContain('Usage: webpack --version'); + expect(pureStdout).toContain('Short: webpack -v'); + expect(pureStdout).toContain( "Description: Output the version number of 'webpack', 'webpack-cli' and 'webpack-dev-server' and commands.", ); - expect(stdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); + expect(pureStdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); }); it('should show help information using the "help -v" option', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['help', '-v'], false); + const { exitCode, stderr, stdout } = run(__dirname, ['help', '-v']); expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); - expect(stdout).toContain('Usage: webpack --version'); - expect(stdout).toContain('Short: webpack -v'); - expect(stdout).toContain( + + const pureStdout = stripAnsi(stdout); + + expect(pureStdout).toContain('Usage: webpack --version'); + expect(pureStdout).toContain('Short: webpack -v'); + expect(pureStdout).toContain( "Description: Output the version number of 'webpack', 'webpack-cli' and 'webpack-dev-server' and commands.", ); - expect(stdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); + expect(pureStdout).toContain('CLI documentation: https://webpack.js.org/api/cli/.'); }); it('should log error for invalid command using the "--help" option', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['--help', 'myCommand'], false); + const { exitCode, stderr, stdout } = run(__dirname, ['--help', 'myCommand']); expect(exitCode).toBe(2); expect(stderr).toContain("Unknown value for '--help' option, please use '--help=verbose'"); @@ -401,7 +461,7 @@ describe('help', () => { }); it('should log error for invalid command using the "--help" option #2', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['--flag', '--help'], false); + const { exitCode, stderr, stdout } = run(__dirname, ['--flag', '--help']); expect(exitCode).toBe(2); expect(stderr).toContain('Incorrect use of help'); @@ -411,7 +471,7 @@ describe('help', () => { }); it('should log error for invalid command using the "--help" option #3', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['serve', '--flag', '--help'], false); + const { exitCode, stderr, stdout } = run(__dirname, ['serve', '--flag', '--help']); expect(exitCode).toBe(2); expect(stderr).toContain('Incorrect use of help'); @@ -421,7 +481,7 @@ describe('help', () => { }); it('should log error for unknown command using command syntax', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['help', 'myCommand'], false); + const { exitCode, stderr, stdout } = run(__dirname, ['help', 'myCommand']); expect(exitCode).toBe(2); expect(stderr).toContain("Can't find and load command 'myCommand'"); @@ -430,7 +490,7 @@ describe('help', () => { }); it('should log error for unknown command using command syntax #2', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['help', 'verbose'], false); + const { exitCode, stderr, stdout } = run(__dirname, ['help', 'verbose']); expect(exitCode).toBe(2); expect(stderr).toContain("Can't find and load command 'verbose'"); @@ -439,7 +499,7 @@ describe('help', () => { }); it('should log error for unknown option using command syntax #2', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['help', '--made'], false); + const { exitCode, stderr, stdout } = run(__dirname, ['help', '--made']); expect(exitCode).toBe(2); expect(stderr).toContain("Unknown option '--made'"); @@ -448,7 +508,7 @@ describe('help', () => { }); it('should log error for unknown option using command syntax #3', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['help', 'serve', '--made'], false); + const { exitCode, stderr, stdout } = run(__dirname, ['help', 'serve', '--made']); expect(exitCode).toBe(2); expect(stderr).toContain("Unknown option '--made'"); @@ -457,7 +517,7 @@ describe('help', () => { }); it('should log error for unknown option using command syntax #4', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['help', 'bui', '--mode'], false); + const { exitCode, stderr, stdout } = run(__dirname, ['help', 'bui', '--mode']); expect(exitCode).toBe(2); expect(stderr).toContain("Can't find and load command 'bui'"); @@ -466,7 +526,7 @@ describe('help', () => { }); it('should log error for invalid command using command syntax #3', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['help', '--mode', 'serve'], false); + const { exitCode, stderr, stdout } = run(__dirname, ['help', '--mode', 'serve']); expect(exitCode).toBe(2); expect(stderr).toContain('Incorrect use of help'); @@ -476,7 +536,7 @@ describe('help', () => { }); it('should log error for invalid command using command syntax #4', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['help', 'serve', '--mode', '--mode'], false); + const { exitCode, stderr, stdout } = run(__dirname, ['help', 'serve', '--mode', '--mode']); expect(exitCode).toBe(2); expect(stderr).toContain('Incorrect use of help'); @@ -486,7 +546,7 @@ describe('help', () => { }); it('should log error for invalid flag with the "--help" option', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['--help', '--my-flag'], false); + const { exitCode, stderr, stdout } = run(__dirname, ['--help', '--my-flag']); expect(exitCode).toBe(2); expect(stderr).toContain('Incorrect use of help'); @@ -496,7 +556,7 @@ describe('help', () => { }); it('should log error for invalid flag with the "--help" option #2', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['--help', 'init', 'info'], false); + const { exitCode, stderr, stdout } = run(__dirname, ['--help', 'init', 'info']); expect(exitCode).toBe(2); expect(stderr).toContain("Unknown value for '--help' option, please use '--help=verbose'"); diff --git a/test/merge/config-absent/merge-config-absent.test.js b/test/merge/config-absent/merge-config-absent.test.js index 5c9d6e05d03..623d8259758 100644 --- a/test/merge/config-absent/merge-config-absent.test.js +++ b/test/merge/config-absent/merge-config-absent.test.js @@ -1,5 +1,7 @@ 'use strict'; +const path = require('path'); + const { run } = require('../../utils/test-utils'); describe('merge flag configuration', () => { @@ -11,6 +13,6 @@ describe('merge flag configuration', () => { // Since the process will exit, nothing on stdout expect(stdout).toBeFalsy(); // Confirm that the user is notified - expect(stderr).toContain(`The specified config file doesn't exist`); + expect(stderr).toContain(`Failed to load '${path.resolve(__dirname, './2.js')}' config`); }); }); diff --git a/test/serve/basic/serve-basic.test.js b/test/serve/basic/serve-basic.test.js index 3ad7aa8def4..a57308f0a00 100644 --- a/test/serve/basic/serve-basic.test.js +++ b/test/serve/basic/serve-basic.test.js @@ -7,9 +7,6 @@ const { runServe, isWebpack5, isDevServer4 } = require('../../utils/test-utils') const testPath = path.resolve(__dirname); -const usageText = 'webpack serve|s [options]'; -const descriptionText = 'Run the webpack dev server'; - describe('basic serve usage', () => { let port; @@ -28,7 +25,7 @@ describe('basic serve usage', () => { } it('should work', async () => { - const { stderr, stdout } = await runServe(__dirname, ['']); + const { stderr, stdout } = await runServe(__dirname, []); expect(stderr).toBeFalsy(); expect(stdout).toContain('main.js'); @@ -36,7 +33,7 @@ describe('basic serve usage', () => { }); it('should work with the "--config" option', async () => { - const { stderr, stdout } = await runServe(__dirname, ['serve', '--config', 'webpack.config.js', '--port', port]); + const { stderr, stdout } = await runServe(__dirname, ['--config', 'serve.config.js', '--port', port]); expect(stderr).toBeFalsy(); expect(stdout).toContain('development'); @@ -45,7 +42,6 @@ describe('basic serve usage', () => { it('should work with the "--config" and "--env" options', async () => { const { stderr, stdout } = await runServe(__dirname, [ - 'serve', '--config', 'function-with-env.config.js', '--env', @@ -63,7 +59,6 @@ describe('basic serve usage', () => { it('should work with the "--config" and "--env" options and expose dev server options', async () => { const { stderr, stdout } = await runServe(__dirname, [ - 'serve', '--config', 'function-with-argv.config.js', '--env', @@ -82,7 +77,7 @@ describe('basic serve usage', () => { }); it('should work in multi compiler mode', async () => { - const { stderr, stdout } = await runServe(__dirname, ['serve', '--config', 'multi.config.js', '--port', port]); + const { stderr, stdout } = await runServe(__dirname, ['--config', 'multi.config.js', '--port', port]); expect(stderr).toBeFalsy(); expect(stdout).toContain('one'); @@ -94,7 +89,7 @@ describe('basic serve usage', () => { // TODO need fix in future, edge case it.skip('should work in multi compiler mode with multiple dev servers', async () => { - const { stderr, stdout } = await runServe(__dirname, ['serve', '--config', 'multi-dev-server.config.js']); + const { stderr, stdout } = await runServe(__dirname, ['--config', 'multi-dev-server.config.js']); expect(stderr).toBeFalsy(); expect(stdout).toContain('one'); @@ -163,14 +158,6 @@ describe('basic serve usage', () => { expect(stdout.match(/HotModuleReplacementPlugin/g)).toBeNull(); }); - it('should log help information and respect the "--no-color" option', async () => { - const { stdout, stderr } = await runServe(__dirname, ['--help', '--no-color']); - - expect(stderr).toBeFalsy(); - expect(stdout).toContain(usageText); - expect(stdout).toContain(descriptionText); - }); - it('should work with the "--client-log-level" option', async () => { const { stdout, stderr } = await runServe(testPath, ['--client-log-level', 'info']); @@ -228,7 +215,7 @@ describe('basic serve usage', () => { }); it('should work with the default "publicPath" option', async () => { - const { stderr, stdout } = await runServe(__dirname, ['serve']); + const { stderr, stdout } = await runServe(__dirname, []); expect(stderr).toBeFalsy(); expect(stdout).toContain('main.js'); @@ -237,7 +224,7 @@ describe('basic serve usage', () => { }); it('should work with the "--output-public-path" option', async () => { - const { stderr, stdout } = await runServe(__dirname, ['serve', '--output-public-path', '/my-public-path/']); + const { stderr, stdout } = await runServe(__dirname, ['--output-public-path', '/my-public-path/']); if (isWebpack5) { expect(stderr).toBeFalsy(); @@ -251,7 +238,7 @@ describe('basic serve usage', () => { }); it('should respect the "publicPath" option from configuration', async () => { - const { stderr, stdout } = await runServe(__dirname, ['serve', '--config', 'output-public-path.config.js']); + const { stderr, stdout } = await runServe(__dirname, ['--config', 'output-public-path.config.js']); expect(stderr).toBeFalsy(); expect(stdout).toContain('main.js'); @@ -260,7 +247,7 @@ describe('basic serve usage', () => { }); it('should respect the "publicPath" option from configuration using multi compiler mode', async () => { - const { stderr, stdout } = await runServe(__dirname, ['serve', '--config', 'multi-output-public-path.config.js', '--port', port]); + const { stderr, stdout } = await runServe(__dirname, ['--config', 'multi-output-public-path.config.js', '--port', port]); expect(stderr).toBeFalsy(); expect(stdout).toContain('one'); @@ -272,7 +259,7 @@ describe('basic serve usage', () => { }); it('should respect the "publicPath" option from configuration (from the "devServer" options)', async () => { - const { stderr, stdout } = await runServe(__dirname, ['serve', '--config', 'dev-server-output-public-path.config.js']); + const { stderr, stdout } = await runServe(__dirname, ['--config', 'dev-server-output-public-path.config.js']); expect(stderr).toBeFalsy(); expect(stdout).toContain('main.js'); @@ -289,13 +276,7 @@ describe('basic serve usage', () => { }); it('should respect the "publicPath" option from configuration using multi compiler mode (from the "devServer" options)', async () => { - const { stderr, stdout } = await runServe(__dirname, [ - 'serve', - '--config', - 'multi-dev-server-output-public-path.config.js', - '--port', - port, - ]); + const { stderr, stdout } = await runServe(__dirname, ['--config', 'multi-dev-server-output-public-path.config.js', '--port', port]); expect(stderr).toBeFalsy(); expect(stderr).toBeFalsy(); @@ -307,6 +288,14 @@ describe('basic serve usage', () => { expect(stdout.match(/HotModuleReplacementPlugin/g)).toBeNull(); }); + it('should work with entries syntax', async () => { + const { stderr, stdout } = await runServe(__dirname, ['./src/entry.js', '--port', port]); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain('development'); + expect(stdout.match(/HotModuleReplacementPlugin/g)).toBeNull(); + }); + it('should log and error on unknown flag', async () => { const { exitCode, stdout, stderr } = await runServe(testPath, ['--port', port, '--unknown-flag']); diff --git a/test/serve/basic/serve.config.js b/test/serve/basic/serve.config.js new file mode 100644 index 00000000000..cef4d803dc3 --- /dev/null +++ b/test/serve/basic/serve.config.js @@ -0,0 +1,7 @@ +const WebpackCLITestPlugin = require('../../utils/webpack-cli-test-plugin'); + +module.exports = { + mode: 'development', + devtool: false, + plugins: [new WebpackCLITestPlugin(['mode'], false, 'hooks.compilation.taps')], +}; diff --git a/test/serve/basic/src/entry.js b/test/serve/basic/src/entry.js new file mode 100644 index 00000000000..a136806e8f1 --- /dev/null +++ b/test/serve/basic/src/entry.js @@ -0,0 +1 @@ +console.log('Entry'); diff --git a/test/serve/help/serve-help.test.js b/test/serve/help/serve-help.test.js index c1f4cc840c2..eb8cabef807 100644 --- a/test/serve/help/serve-help.test.js +++ b/test/serve/help/serve-help.test.js @@ -1,11 +1,12 @@ const { runServe, isWebpack5 } = require('../../utils/test-utils'); -const usageText = 'webpack serve|s [options]'; +const usageText = 'webpack serve|s [entries...] [options]'; const descriptionText = 'Run the webpack dev server'; describe('serve help', () => { - it('should output serve help', async () => { + it('should log help information', async () => { const { stderr, stdout, exitCode } = await runServe(__dirname, ['--help']); + expect(stderr).toBeFalsy(); expect(exitCode).toBe(0); expect(stdout).toContain(descriptionText); @@ -18,15 +19,25 @@ describe('serve help', () => { expect(stdout).toContain('--open [value]'); }); - it('should output all flags when verbose help is set', async () => { + it('should log help information using "verbose"', async () => { const { stderr, stdout, exitCode } = await runServe(__dirname, ['--help', 'verbose']); + expect(stderr).toBeFalsy(); expect(exitCode).toBe(0); expect(stdout).toContain(descriptionText); expect(stdout).toContain(usageText); expect(stdout).toContain('Options:'); + if (isWebpack5) { expect(stdout).toContain('--cache-type'); } }); + + it('should log help information and respect the "--no-color" option', async () => { + const { stdout, stderr } = await runServe(__dirname, ['--help', '--no-color']); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain(usageText); + expect(stdout).toContain(descriptionText); + }); }); diff --git a/test/unknown/unknown.test.js b/test/unknown/unknown.test.js index ad3b6c97ec3..c87fbd5bcd2 100644 --- a/test/unknown/unknown.test.js +++ b/test/unknown/unknown.test.js @@ -203,7 +203,7 @@ describe('unknown behaviour', () => { const { exitCode, stderr, stdout } = run(__dirname, ['qqq'], true, [], { TERM_PROGRAM: false }); expect(exitCode).toBe(2); - expect(stripAnsi(stderr)).toContain("Unknown command 'qqq'"); + expect(stripAnsi(stderr)).toContain("Unknown command or entry 'qqq'"); expect(stripAnsi(stderr)).toContain("Run 'webpack --help' to see available commands and options"); expect(stdout).toBeFalsy(); }); @@ -212,7 +212,7 @@ describe('unknown behaviour', () => { const { exitCode, stderr, stdout } = run(__dirname, ['server'], true, [], { TERM_PROGRAM: false }); expect(exitCode).toBe(2); - expect(stripAnsi(stderr)).toContain("Unknown command 'server'"); + expect(stripAnsi(stderr)).toContain("Unknown command or entry 'server'"); expect(stripAnsi(stderr)).toContain("Did you mean 'serve' (alias 's')?"); expect(stripAnsi(stderr)).toContain("Run 'webpack --help' to see available commands and options"); expect(stdout).toBeFalsy(); diff --git a/test/watch/basic/basic.test.js b/test/watch/basic/basic.test.js index 34fee148278..0d24c6dda3a 100644 --- a/test/watch/basic/basic.test.js +++ b/test/watch/basic/basic.test.js @@ -83,6 +83,41 @@ describe('basic', () => { }); }); + it('should recompile upon file change using the `watch` command and entries syntax', (done) => { + const proc = runAndGetWatchProc(__dirname, ['watch', './src/entry.js', '--mode', 'development'], false, '', true); + + let modified = false; + + const wordsInStatsv5Entries = ['asset', 'entry.js', 'compiled successfully']; + + proc.stdout.on('data', (chunk) => { + const data = stripAnsi(chunk.toString()); + + if (data.includes('entry.js')) { + if (isWebpack5) { + for (const word of wordsInStatsv5Entries) { + expect(data).toContain(word); + } + } else { + for (const word of wordsInStatsv4) { + expect(data).toContain(word); + } + } + + if (!modified) { + process.nextTick(() => { + writeFileSync(resolve(__dirname, './src/entry.js'), `console.log('watch flag test');`); + }); + + modified = true; + } else { + proc.kill(); + done(); + } + } + }); + }); + it('should recompile upon file change using the `command` option and the `--watch` option and log warning', (done) => { const proc = runAndGetWatchProc(__dirname, ['watch', '--watch', '--mode', 'development'], false, '', true); diff --git a/test/watch/basic/src/entry.js b/test/watch/basic/src/entry.js new file mode 100644 index 00000000000..1d8734ee1c8 --- /dev/null +++ b/test/watch/basic/src/entry.js @@ -0,0 +1 @@ +console.log('watch flag test'); From 311bae336d83424c800e553b6ef40242d967685c Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Thu, 28 Jan 2021 15:30:22 +0530 Subject: [PATCH 11/29] fix: improve description for 'configtest' command (#2379) --- OPTIONS.md | 2 +- packages/configtest/package.json | 2 +- packages/configtest/src/index.ts | 2 +- packages/webpack-cli/README.md | 12 ++++++------ 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/OPTIONS.md b/OPTIONS.md index f87c5a7269e..9cf47d8cec7 100644 --- a/OPTIONS.md +++ b/OPTIONS.md @@ -794,7 +794,7 @@ Global options: Commands: build|bundle|b [entries...] [options] Run webpack (default command, can be omitted). - configtest|t [config-path] Tests webpack configuration against validation errors. + configtest|t [config-path] Validate a webpack configuration. help|h [command] [option] Display help for commands and options. info|i [options] Outputs information about your system. init|c [scaffold...] [options] Initialize a new webpack configuration. diff --git a/packages/configtest/package.json b/packages/configtest/package.json index 6b0857083b0..b33a1bd3d15 100644 --- a/packages/configtest/package.json +++ b/packages/configtest/package.json @@ -1,7 +1,7 @@ { "name": "@webpack-cli/configtest", "version": "1.0.0", - "description": "Tests webpack configuration against validation errors.", + "description": "Validate a webpack configuration.", "main": "lib/index.js", "types": "lib/index.d.ts", "license": "MIT", diff --git a/packages/configtest/src/index.ts b/packages/configtest/src/index.ts index f9b5b92304a..50e4a3d9205 100644 --- a/packages/configtest/src/index.ts +++ b/packages/configtest/src/index.ts @@ -6,7 +6,7 @@ class ConfigTestCommand { { name: 'configtest [config-path]', alias: 't', - description: 'Tests webpack configuration against validation errors.', + description: 'Validate a webpack configuration.', pkg: '@webpack-cli/configtest', }, [], diff --git a/packages/webpack-cli/README.md b/packages/webpack-cli/README.md index ca7f2204b8d..a7248a715c6 100644 --- a/packages/webpack-cli/README.md +++ b/packages/webpack-cli/README.md @@ -63,17 +63,17 @@ npx webpack-cli --help verbose ### Available Commands ``` - build|bundle|b [options] Run webpack (default command, can be omitted). - watch|w [options] Run webpack and watch for files changes. - version|v [commands...] Output the version number of 'webpack', 'webpack-cli' and 'webpack-dev-server' and commands. + build|bundle|b [entries...] [options] Run webpack (default command, can be omitted). + configtest|t [config-path] Validate a webpack configuration. help|h [command] [option] Display help for commands and options. - serve|s [options] Run the webpack dev server. info|i [options] Outputs information about your system. - init|c [options] [scaffold...] Initialize a new webpack configuration. + init|c [scaffold...] [options] Initialize a new webpack configuration. loader|l [output-path] Scaffold a loader. migrate|m [new-config-path] Migrate a configuration to a new version. - configtest|t [config-path] Tests webpack configuration against validation errors. plugin|p [output-path] Scaffold a plugin. + serve|s [entries...] [options] Run the webpack dev server. + version|v [commands...] Output the version number of 'webpack', 'webpack-cli' and 'webpack-dev-server' and commands. + watch|w [entries...] [options] Run webpack and watch for files changes. ``` ### webpack 4 From f9ce1d30b83bf0e0b4d91498d012c13c208e6e67 Mon Sep 17 00:00:00 2001 From: Alexander Akait <4567934+alexander-akait@users.noreply.github.com> Date: Thu, 28 Jan 2021 17:03:37 +0300 Subject: [PATCH 12/29] fix: error message on invalid plugin options (#2380) --- package.json | 2 +- packages/serve/src/index.ts | 2 +- packages/webpack-cli/lib/webpack-cli.js | 26 +++--- .../invalid-schema/invalid-schema.test.js | 89 ++++++++++++++++++- ....config.mock.js => webpack.mock.config.js} | 0 .../webpack.plugin-mock.config.js | 10 +++ yarn.lock | 45 +++++----- 7 files changed, 139 insertions(+), 35 deletions(-) rename test/error/invalid-schema/{webpack.config.mock.js => webpack.mock.config.js} (100%) create mode 100644 test/error/invalid-schema/webpack.plugin-mock.config.js diff --git a/package.json b/package.json index f029c615ce4..504d74f5ff9 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ "strip-ansi": "^6.0.0", "ts-jest": "^26.4.3", "typescript": "^4.1.3", - "webpack": "^5.17.0", + "webpack": "^5.18.0", "webpack-bundle-analyzer": "^4.3.0", "webpack-dev-server": "^3.11.1", "yeoman-test": "^2.7.0" diff --git a/packages/serve/src/index.ts b/packages/serve/src/index.ts index 5b72fd66a3a..508b5cee234 100644 --- a/packages/serve/src/index.ts +++ b/packages/serve/src/index.ts @@ -113,7 +113,7 @@ class ServeCommand { try { servers = await startDevServer(compiler, devServerOptions, options, logger); } catch (error) { - if (error.name === 'ValidationError') { + if (cli.isValidationError(error)) { logger.error(error.message); } else { logger.error(error); diff --git a/packages/webpack-cli/lib/webpack-cli.js b/packages/webpack-cli/lib/webpack-cli.js index b945f9b189f..0baf614ee13 100644 --- a/packages/webpack-cli/lib/webpack-cli.js +++ b/packages/webpack-cli/lib/webpack-cli.js @@ -1172,7 +1172,13 @@ class WebpackCLI { } } catch (error) { logger.error(`Failed to load '${configPath}' config`); - logger.error(error); + + if (this.isValidationError(error)) { + logger.error(error.message); + } else { + logger.error(error); + } + process.exit(2); } @@ -1602,15 +1608,15 @@ class WebpackCLI { return compiler.options.watchOptions && compiler.options.watchOptions.stdin; } - async createCompiler(options, callback) { - const isValidationError = (error) => { - // https://github.com/webpack/webpack/blob/master/lib/index.js#L267 - // https://github.com/webpack/webpack/blob/v4.44.2/lib/webpack.js#L90 - const ValidationError = this.webpack.ValidationError || this.webpack.WebpackOptionsValidationError; + isValidationError(error) { + // https://github.com/webpack/webpack/blob/master/lib/index.js#L267 + // https://github.com/webpack/webpack/blob/v4.44.2/lib/webpack.js#L90 + const ValidationError = this.webpack.ValidationError || this.webpack.WebpackOptionsValidationError; - return error instanceof ValidationError; - }; + return error instanceof ValidationError || error.name === 'ValidationError'; + } + async createCompiler(options, callback) { let config = await this.resolveConfig(options); config = await this.applyOptions(config, options); @@ -1623,7 +1629,7 @@ class WebpackCLI { config.options, callback ? (error, stats) => { - if (isValidationError(error)) { + if (error && this.isValidationError(error)) { logger.error(error.message); process.exit(2); } @@ -1633,7 +1639,7 @@ class WebpackCLI { : callback, ); } catch (error) { - if (isValidationError(error)) { + if (this.isValidationError(error)) { logger.error(error.message); } else { logger.error(error); diff --git a/test/error/invalid-schema/invalid-schema.test.js b/test/error/invalid-schema/invalid-schema.test.js index cfcb54542da..05c04c8d735 100644 --- a/test/error/invalid-schema/invalid-schema.test.js +++ b/test/error/invalid-schema/invalid-schema.test.js @@ -3,15 +3,23 @@ const { run, isWebpack5 } = require('../../utils/test-utils'); describe('invalid schema', () => { it('should log error on invalid config', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['--config', './webpack.config.mock.js']); + const { exitCode, stderr, stdout } = run(__dirname, ['--config', './webpack.mock.config.js']); expect(exitCode).toEqual(2); expect(stderr).toContain('Invalid configuration object'); expect(stdout).toBeFalsy(); }); + it('should log error on invalid plugin options', () => { + const { exitCode, stderr, stdout } = run(__dirname, ['--config', './webpack.plugin-mock.config.js']); + + expect(exitCode).toEqual(2); + expect(stderr).toContain(isWebpack5 ? 'Invalid options object' : 'Invalid Options'); + expect(stdout).toBeFalsy(); + }); + it('should log error on invalid config using the "bundle" command', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['bundle', '--config', './webpack.config.mock.js']); + const { exitCode, stderr, stdout } = run(__dirname, ['bundle', '--config', './webpack.mock.config.js']); expect(exitCode).toEqual(2); expect(stderr).toContain('Invalid configuration object'); @@ -19,7 +27,7 @@ describe('invalid schema', () => { }); it('should log error on invalid config using the "serve" command', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['serve', '--config', './webpack.config.mock.js']); + const { exitCode, stderr, stdout } = run(__dirname, ['serve', '--config', './webpack.mock.config.js']); expect(exitCode).toEqual(2); expect(stderr).toContain('Invalid configuration object'); @@ -41,6 +49,21 @@ describe('invalid schema', () => { expect(stdout).toBeFalsy(); }); + it('should log error on invalid option using "build" command', () => { + const { exitCode, stderr, stdout } = run(__dirname, ['build', '--mode', 'Yukihira']); + + expect(exitCode).toEqual(2); + + if (isWebpack5) { + expect(stderr).toContain("Invalid value 'Yukihira' for the '--mode' option"); + expect(stderr).toContain("Expected: 'development | production | none'"); + } else { + expect(stderr).toContain('Invalid configuration object'); + } + + expect(stdout).toBeFalsy(); + }); + it('should log error on invalid option using "bundle" command', () => { const { exitCode, stderr, stdout } = run(__dirname, ['bundle', '--mode', 'Yukihira']); @@ -56,6 +79,51 @@ describe('invalid schema', () => { expect(stdout).toBeFalsy(); }); + it('should log error on invalid option using "b" command', () => { + const { exitCode, stderr, stdout } = run(__dirname, ['b', '--mode', 'Yukihira']); + + expect(exitCode).toEqual(2); + + if (isWebpack5) { + expect(stderr).toContain("Invalid value 'Yukihira' for the '--mode' option"); + expect(stderr).toContain("Expected: 'development | production | none'"); + } else { + expect(stderr).toContain('Invalid configuration object'); + } + + expect(stdout).toBeFalsy(); + }); + + it('should log error on invalid option using "watch" command', () => { + const { exitCode, stderr, stdout } = run(__dirname, ['watch', '--mode', 'Yukihira']); + + expect(exitCode).toEqual(2); + + if (isWebpack5) { + expect(stderr).toContain("Invalid value 'Yukihira' for the '--mode' option"); + expect(stderr).toContain("Expected: 'development | production | none'"); + } else { + expect(stderr).toContain('Invalid configuration object'); + } + + expect(stdout).toBeFalsy(); + }); + + it('should log error on invalid option using "w" command', () => { + const { exitCode, stderr, stdout } = run(__dirname, ['w', '--mode', 'Yukihira']); + + expect(exitCode).toEqual(2); + + if (isWebpack5) { + expect(stderr).toContain("Invalid value 'Yukihira' for the '--mode' option"); + expect(stderr).toContain("Expected: 'development | production | none'"); + } else { + expect(stderr).toContain('Invalid configuration object'); + } + + expect(stdout).toBeFalsy(); + }); + it('should log error on invalid option using "server" command', () => { const { exitCode, stderr, stdout } = run(__dirname, ['serve', '--mode', 'Yukihira']); @@ -70,4 +138,19 @@ describe('invalid schema', () => { expect(stdout).toBeFalsy(); }); + + it('should log error on invalid option using "s" command', () => { + const { exitCode, stderr, stdout } = run(__dirname, ['s', '--mode', 'Yukihira']); + + expect(exitCode).toEqual(2); + + if (isWebpack5) { + expect(stderr).toContain("Invalid value 'Yukihira' for the '--mode' option"); + expect(stderr).toContain("Expected: 'development | production | none'"); + } else { + expect(stderr).toContain('Invalid configuration object'); + } + + expect(stdout).toBeFalsy(); + }); }); diff --git a/test/error/invalid-schema/webpack.config.mock.js b/test/error/invalid-schema/webpack.mock.config.js similarity index 100% rename from test/error/invalid-schema/webpack.config.mock.js rename to test/error/invalid-schema/webpack.mock.config.js diff --git a/test/error/invalid-schema/webpack.plugin-mock.config.js b/test/error/invalid-schema/webpack.plugin-mock.config.js new file mode 100644 index 00000000000..24a228b9d92 --- /dev/null +++ b/test/error/invalid-schema/webpack.plugin-mock.config.js @@ -0,0 +1,10 @@ +const webpack = require('webpack'); + +module.exports = { + mode: 'development', + plugins: [ + new webpack.BannerPlugin({ + unknown: 'unknown', + }), + ], +}; diff --git a/yarn.lock b/yarn.lock index 0dbfd643050..a05832ed73a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1895,11 +1895,16 @@ jest-diff "^26.0.0" pretty-format "^26.0.0" -"@types/json-schema@*", "@types/json-schema@^7.0.3", "@types/json-schema@^7.0.6": +"@types/json-schema@*", "@types/json-schema@^7.0.3": version "7.0.6" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== +"@types/json-schema@^7.0.6": + version "7.0.7" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad" + integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA== + "@types/keyv@*": version "3.1.1" resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.1.tgz#e45a45324fca9dab716ab1230ee249c9fb52cfa7" @@ -2863,15 +2868,15 @@ browser-process-hrtime@^1.0.0: integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== browserslist@^4.14.5: - version "4.15.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.15.0.tgz#3d48bbca6a3f378e86102ffd017d9a03f122bdb0" - integrity sha512-IJ1iysdMkGmjjYeRlDU8PQejVwxvVO5QOfXH7ylW31GO6LwNRSmm/SgRXtNsEXqMLl2e+2H5eEJ7sfynF8TCaQ== + version "4.16.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.1.tgz#bf757a2da376b3447b800a16f0f1c96358138766" + integrity sha512-UXhDrwqsNcpTYJBTZsbGATDxZbiVDsx6UjpmRUmtnP10pr8wAYr5LgFoEFw9ixriQH2mv/NX2SfGzE/o8GndLA== dependencies: - caniuse-lite "^1.0.30001164" + caniuse-lite "^1.0.30001173" colorette "^1.2.1" - electron-to-chromium "^1.3.612" + electron-to-chromium "^1.3.634" escalade "^3.1.1" - node-releases "^1.1.67" + node-releases "^1.1.69" bs-logger@0.x: version "0.2.6" @@ -3066,10 +3071,10 @@ camelcase@^6.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== -caniuse-lite@^1.0.30001164: - version "1.0.30001165" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001165.tgz#32955490d2f60290bb186bb754f2981917fa744f" - integrity sha512-8cEsSMwXfx7lWSUMA2s08z9dIgsnR5NAqjXP23stdsU3AUWkCr/rr4s4OFtHXn5XXr6+7kam3QFVoYyXNPdJPA== +caniuse-lite@^1.0.30001173: + version "1.0.30001180" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001180.tgz#67abcd6d1edf48fa5e7d1e84091d1d65ab76e33b" + integrity sha512-n8JVqXuZMVSPKiPiypjFtDTXc4jWIdjxull0f92WLo7e1MSi3uJ3NvveakSh/aCl1QKFAvIz3vIj0v+0K+FrXw== capture-exit@^2.0.0: version "2.0.0" @@ -4147,10 +4152,10 @@ ejs@^3.0.1: dependencies: jake "^10.6.1" -electron-to-chromium@^1.3.612: - version "1.3.621" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.621.tgz#0bbe2100ef0b28f88d0b1101fbdf433312f69be0" - integrity sha512-FeIuBzArONbAmKmZIsZIFGu/Gc9AVGlVeVbhCq+G2YIl6QkT0TDn2HKN/FMf1btXEB9kEmIuQf3/lBTVAbmFOg== +electron-to-chromium@^1.3.634: + version "1.3.647" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.647.tgz#8f1750ab7a5137f1a9a27f8f4ebdf550e08ae10b" + integrity sha512-Or2Nu8TjkmSywY9hk85K/Y6il28hchlonITz30fkC87qvSNupQl29O12BzDDDTnUFlo6kEIFL2QGSpkZDMxH8g== elegant-spinner@^1.0.1: version "1.0.1" @@ -8019,10 +8024,10 @@ node-preload@^0.2.1: dependencies: process-on-spawn "^1.0.0" -node-releases@^1.1.67: - version "1.1.67" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.67.tgz#28ebfcccd0baa6aad8e8d4d8fe4cbc49ae239c12" - integrity sha512-V5QF9noGFl3EymEwUYzO+3NTDpGfQB4ve6Qfnzf3UNydMhjQRVPR1DZTuvWiLzaFJYw2fmDwAfnRNEVb64hSIg== +node-releases@^1.1.69: + version "1.1.70" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.70.tgz#66e0ed0273aa65666d7fe78febe7634875426a08" + integrity sha512-Slf2s69+2/uAD79pVVQo8uSiC34+g8GWY8UH2Qtqv34ZfhYrxpYpfzs9Js9d6O0mbDmALuxaTlplnBTnSELcrw== nopt@^4.0.1: version "4.0.3" @@ -11072,7 +11077,7 @@ webpack-sources@^2.1.1: source-list-map "^2.0.1" source-map "^0.6.1" -webpack@^5.17.0: +webpack@^5.18.0: version "5.18.0" resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.18.0.tgz#bbcf13094aa0da0534d513f27d7ee72d74e499c6" integrity sha512-RmiP/iy6ROvVe/S+u0TrvL/oOmvP+2+Bs8MWjvBwwY/j82Q51XJyDJ75m0QAGntL1Wx6B//Xc0+4VPP/hlNHmw== From 529e9f01372a5cc6e910dd65528dc759819ac823 Mon Sep 17 00:00:00 2001 From: Alexander Akait <4567934+alexander-akait@users.noreply.github.com> Date: Fri, 29 Jan 2021 18:38:36 +0300 Subject: [PATCH 13/29] refactor: code --- .eslintignore | 11 +- .eslintrc.js | 1 + .prettierignore | 9 +- .../resolveConfig/resolveConfig.test.js | 14 +- packages/webpack-cli/bin/cli.js | 16 +- packages/webpack-cli/lib/bootstrap.js | 6 +- packages/webpack-cli/lib/index.js | 6 +- packages/webpack-cli/lib/plugins/CLIPlugin.js | 9 +- .../lib/utils/get-package-manager.js | 5 +- packages/webpack-cli/lib/utils/index.js | 45 ++++ packages/webpack-cli/lib/utils/logger.js | 10 +- .../webpack-cli/lib/utils/package-exists.js | 4 +- .../lib/utils/prompt-installation.js | 23 +- packages/webpack-cli/lib/utils/run-command.js | 4 +- packages/webpack-cli/lib/webpack-cli.js | 244 +++++++++--------- 15 files changed, 233 insertions(+), 174 deletions(-) create mode 100644 packages/webpack-cli/lib/utils/index.js diff --git a/.eslintignore b/.eslintignore index acb5f4123c7..b6038bd2368 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,13 +1,18 @@ -__testfixtures__ coverage +.nyc_output node_modules -packages/**/lib +dist +packages/configtest/lib +packages/generators/lib +packages/info/lib +packages/init/lib +packages/serve/lib test/**/dist/ test/**/bin/ test/**/binary/ test/**/index.js -test/typescript/webpack.config.ts test/config/error-commonjs/syntax-error.js test/config/error-mjs/syntax-error.mjs test/config/error-array/webpack.config.js test/configtest/with-config-path/syntax-error.config.js +packages/generators/src/utils/__tests__/recursive-parser/__testfixtures__ diff --git a/.eslintrc.js b/.eslintrc.js index fa66f1777f4..9e59b158b59 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -21,6 +21,7 @@ module.exports = { 'no-caller': 'error', 'no-extra-bind': 'error', 'no-loop-func': 'error', + 'no-undef': 'error', }, overrides: [ { diff --git a/.prettierignore b/.prettierignore index c45e6482b38..877e50a1666 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,13 +1,18 @@ coverage .nyc_output node_modules +dist +packages/configtest/lib +packages/generators/lib +packages/info/lib +packages/init/lib +packages/serve/lib test/**/dist/ test/**/bin/ test/**/binary/ test/**/index.js test/config/error-commonjs/syntax-error.js test/config/error-mjs/syntax-error.mjs +test/configtest/with-config-path/syntax-error.config.js packages/webpack-cli/__tests__/test-assets/.yo-rc.json test/build-errors/stats.json -packages/**/lib -test/configtest/with-config-path/syntax-error.config.js diff --git a/packages/webpack-cli/__tests__/resolveConfig/resolveConfig.test.js b/packages/webpack-cli/__tests__/resolveConfig/resolveConfig.test.js index 4522bfc3f2c..d3002fb0225 100644 --- a/packages/webpack-cli/__tests__/resolveConfig/resolveConfig.test.js +++ b/packages/webpack-cli/__tests__/resolveConfig/resolveConfig.test.js @@ -5,11 +5,11 @@ const config2 = require('./webpack.config2.cjs'); const arrayConfig = require('./webpack.config.cjs'); const promiseConfig = require('./webpack.promise.config.cjs'); -const resolveConfig = new WebpackCLI().resolveConfig; +const cli = new WebpackCLI(); describe('resolveConfig', function () { it('should handle merge properly', async () => { - const result = await resolveConfig({ + const result = await cli.resolveConfig({ merge: true, config: [resolve(__dirname, './webpack.config.cjs')], }); @@ -27,7 +27,7 @@ describe('resolveConfig', function () { }); it('should return array for multiple config', async () => { - const result = await resolveConfig({ + const result = await cli.resolveConfig({ config: [resolve(__dirname, './webpack.config1.cjs'), resolve(__dirname, './webpack.config2.cjs')], }); const expectedOptions = [config1, config2]; @@ -36,20 +36,20 @@ describe('resolveConfig', function () { }); it('should return config object for single config', async () => { - const result = await resolveConfig({ config: [resolve(__dirname, './webpack.config1.cjs')] }); + const result = await cli.resolveConfig({ config: [resolve(__dirname, './webpack.config1.cjs')] }); expect(result.options).toEqual(config1); }); it('should return resolved config object for promise config', async () => { - const result = await resolveConfig({ config: [resolve(__dirname, './webpack.promise.config.cjs')] }); + const result = await cli.resolveConfig({ config: [resolve(__dirname, './webpack.promise.config.cjs')] }); const expectedOptions = await promiseConfig(); expect(result.options).toEqual(expectedOptions); }); it('should handle configs returning different types', async () => { - const result = await resolveConfig({ + const result = await cli.resolveConfig({ config: [resolve(__dirname, './webpack.promise.config.cjs'), resolve(__dirname, './webpack.config.cjs')], }); const resolvedPromiseConfig = await promiseConfig(); @@ -59,7 +59,7 @@ describe('resolveConfig', function () { }); it('should handle different env formats', async () => { - const result = await resolveConfig({ + const result = await cli.resolveConfig({ argv: { env: { test: true, name: 'Hisoka' } }, config: [resolve(__dirname, './env.webpack.config.cjs')], }); diff --git a/packages/webpack-cli/bin/cli.js b/packages/webpack-cli/bin/cli.js index d309c0a985f..c78e0935e9f 100755 --- a/packages/webpack-cli/bin/cli.js +++ b/packages/webpack-cli/bin/cli.js @@ -1,15 +1,11 @@ #!/usr/bin/env node 'use strict'; - require('v8-compile-cache'); const importLocal = require('import-local'); const runCLI = require('../lib/bootstrap'); -const { yellow } = require('colorette'); -const { error, success } = require('../lib/utils/logger'); -const packageExists = require('../lib/utils/package-exists'); -const promptInstallation = require('../lib/utils/prompt-installation'); +const utils = require('../lib/utils'); // Prefer the local installation of `webpack-cli` if (importLocal(__filename)) { @@ -18,19 +14,21 @@ if (importLocal(__filename)) { process.title = 'webpack'; -if (packageExists('webpack')) { +if (utils.packageExists('webpack')) { runCLI(process.argv); } else { + const { promptInstallation, logger, colors } = utils; + promptInstallation('webpack', () => { - error(`It looks like ${yellow('webpack')} is not installed.`); + utils.logger.error(`It looks like ${colors.bold('webpack')} is not installed.`); }) .then(() => { - success(`${yellow('webpack')} was installed successfully.`); + logger.success(`${colors.bold('webpack')} was installed successfully.`); runCLI(process.argv); }) .catch(() => { - error(`Action Interrupted, Please try once again or install ${yellow('webpack')} manually.`); + logger.error(`Action Interrupted, Please try once again or install ${colors.bold('webpack')} manually.`); process.exit(2); }); diff --git a/packages/webpack-cli/lib/bootstrap.js b/packages/webpack-cli/lib/bootstrap.js index ffb65e53c08..c01ca2b7ce7 100644 --- a/packages/webpack-cli/lib/bootstrap.js +++ b/packages/webpack-cli/lib/bootstrap.js @@ -1,7 +1,5 @@ const WebpackCLI = require('./webpack-cli'); -const logger = require('./utils/logger'); - -process.title = 'webpack-cli'; +const utils = require('./utils'); const runCLI = async (args) => { try { @@ -10,7 +8,7 @@ const runCLI = async (args) => { await cli.run(args); } catch (error) { - logger.error(error); + utils.logger.error(error); process.exit(2); } }; diff --git a/packages/webpack-cli/lib/index.js b/packages/webpack-cli/lib/index.js index fa7a933054f..0af01e8eb7c 100644 --- a/packages/webpack-cli/lib/index.js +++ b/packages/webpack-cli/lib/index.js @@ -1,7 +1,5 @@ const CLI = require('./webpack-cli'); -const logger = require('./utils/logger'); -const getPackageManager = require('./utils/get-package-manager'); +const utils = require('./utils'); module.exports = CLI; -// export additional utils used by other packages -module.exports.utils = { logger, getPackageManager }; +module.exports.utils = utils; diff --git a/packages/webpack-cli/lib/plugins/CLIPlugin.js b/packages/webpack-cli/lib/plugins/CLIPlugin.js index 584d6e21a07..350ee33e573 100644 --- a/packages/webpack-cli/lib/plugins/CLIPlugin.js +++ b/packages/webpack-cli/lib/plugins/CLIPlugin.js @@ -1,13 +1,10 @@ -const packageExists = require('../utils/package-exists'); -const webpack = packageExists('webpack') ? require('webpack') : undefined; - class CLIPlugin { constructor(options) { this.options = options; } setupHotPlugin(compiler) { - const { HotModuleReplacementPlugin } = compiler.webpack || webpack; + const { HotModuleReplacementPlugin } = compiler.webpack || require('webpack'); const hotModuleReplacementPlugin = Boolean(compiler.options.plugins.find((plugin) => plugin instanceof HotModuleReplacementPlugin)); if (!hotModuleReplacementPlugin) { @@ -16,7 +13,7 @@ class CLIPlugin { } setupPrefetchPlugin(compiler) { - const { PrefetchPlugin } = compiler.webpack || webpack; + const { PrefetchPlugin } = compiler.webpack || require('webpack'); new PrefetchPlugin(null, this.options.prefetch).apply(compiler); } @@ -32,7 +29,7 @@ class CLIPlugin { } setupProgressPlugin(compiler) { - const { ProgressPlugin } = compiler.webpack || webpack; + const { ProgressPlugin } = compiler.webpack || require('webpack'); const progressPlugin = Boolean(compiler.options.plugins.find((plugin) => plugin instanceof ProgressPlugin)); if (!progressPlugin) { diff --git a/packages/webpack-cli/lib/utils/get-package-manager.js b/packages/webpack-cli/lib/utils/get-package-manager.js index d25f3564778..616e64b31c2 100644 --- a/packages/webpack-cli/lib/utils/get-package-manager.js +++ b/packages/webpack-cli/lib/utils/get-package-manager.js @@ -1,8 +1,9 @@ const fs = require('fs'); const path = require('path'); -const logger = require('./logger'); const { sync } = require('execa'); +const utils = require('./index'); + /** * * Returns the name of package manager to use, @@ -56,7 +57,7 @@ function getPackageManager() { return 'pnpm'; } } catch (e) { - logger.error('No package manager found.'); + utils.logger.error('No package manager found.'); process.exit(2); } } diff --git a/packages/webpack-cli/lib/utils/index.js b/packages/webpack-cli/lib/utils/index.js new file mode 100644 index 00000000000..223e9c0cf3f --- /dev/null +++ b/packages/webpack-cli/lib/utils/index.js @@ -0,0 +1,45 @@ +module.exports = { + get colors() { + return require('colorette'); + }, + + get levenshtein() { + return require('fastest-levenshtein'); + }, + + get interpret() { + return require('interpret'); + }, + + get rechoir() { + return require('rechoir'); + }, + + get capitalizeFirstLetter() { + return require('./capitalize-first-letter'); + }, + + get getPackageManager() { + return require('./get-package-manager'); + }, + + get logger() { + return require('./logger'); + }, + + get packageExists() { + return require('./package-exists'); + }, + + get promptInstallation() { + return require('./prompt-installation'); + }, + + get runCommand() { + return require('./run-command'); + }, + + get toKebabCase() { + return require('./to-kebab-case'); + }, +}; diff --git a/packages/webpack-cli/lib/utils/logger.js b/packages/webpack-cli/lib/utils/logger.js index 3afafc1ad44..b0d37baafd8 100644 --- a/packages/webpack-cli/lib/utils/logger.js +++ b/packages/webpack-cli/lib/utils/logger.js @@ -1,11 +1,11 @@ +const utils = require('./index'); const util = require('util'); -const { red, cyan, yellow, green } = require('colorette'); module.exports = { - error: (val) => console.error(`[webpack-cli] ${red(util.format(val))}`), - warn: (val) => console.warn(`[webpack-cli] ${yellow(val)}`), - info: (val) => console.info(`[webpack-cli] ${cyan(val)}`), - success: (val) => console.log(`[webpack-cli] ${green(val)}`), + error: (val) => console.error(`[webpack-cli] ${utils.colors.red(util.format(val))}`), + warn: (val) => console.warn(`[webpack-cli] ${utils.colors.yellow(val)}`), + info: (val) => console.info(`[webpack-cli] ${utils.colors.cyan(val)}`), + success: (val) => console.log(`[webpack-cli] ${utils.colors.green(val)}`), log: (val) => console.log(`[webpack-cli] ${val}`), raw: (val) => console.log(val), }; diff --git a/packages/webpack-cli/lib/utils/package-exists.js b/packages/webpack-cli/lib/utils/package-exists.js index 48211cfb938..532b619c8b2 100644 --- a/packages/webpack-cli/lib/utils/package-exists.js +++ b/packages/webpack-cli/lib/utils/package-exists.js @@ -1,4 +1,4 @@ -function getPkg(packageName) { +function packageExists(packageName) { try { return require.resolve(packageName); } catch (error) { @@ -6,4 +6,4 @@ function getPkg(packageName) { } } -module.exports = getPkg; +module.exports = packageExists; diff --git a/packages/webpack-cli/lib/utils/prompt-installation.js b/packages/webpack-cli/lib/utils/prompt-installation.js index d025d80e6ff..d477701a03b 100644 --- a/packages/webpack-cli/lib/utils/prompt-installation.js +++ b/packages/webpack-cli/lib/utils/prompt-installation.js @@ -1,9 +1,5 @@ const { prompt } = require('enquirer'); -const { green } = require('colorette'); -const runCommand = require('./run-command'); -const getPackageManager = require('./get-package-manager'); -const packageExists = require('./package-exists'); -const logger = require('./logger'); +const utils = require('./index'); /** * @@ -11,10 +7,10 @@ const logger = require('./logger'); * @param preMessage Message to show before the question */ async function promptInstallation(packageName, preMessage) { - const packageManager = getPackageManager(); + const packageManager = utils.getPackageManager(); if (!packageManager) { - logger.error("Can't find package manager"); + utils.logger.error("Can't find package manager"); process.exit(2); } @@ -24,6 +20,7 @@ async function promptInstallation(packageName, preMessage) { // yarn uses 'add' command, rest npm and pnpm both use 'install' const commandToBeRun = `${packageManager} ${[packageManager === 'yarn' ? 'add' : 'install', '-D', packageName].join(' ')}`; + const { colors } = utils; let installConfirm; @@ -32,25 +29,27 @@ async function promptInstallation(packageName, preMessage) { { type: 'confirm', name: 'installConfirm', - message: `Would you like to install '${green(packageName)}' package? (That will run '${green(commandToBeRun)}')`, + message: `Would you like to install '${colors.green(packageName)}' package? (That will run '${colors.green( + commandToBeRun, + )}')`, initial: 'Y', stdout: process.stderr, }, ])); } catch (error) { - logger.error(error); + utils.logger.error(error); process.exit(2); } if (installConfirm) { try { - await runCommand(commandToBeRun); + await utils.runCommand(commandToBeRun); } catch (error) { - logger.error(error); + utils.logger.error(error); process.exit(2); } - return packageExists(packageName); + return utils.packageExists(packageName); } process.exit(2); diff --git a/packages/webpack-cli/lib/utils/run-command.js b/packages/webpack-cli/lib/utils/run-command.js index 4ed493f3ea3..58463661c27 100644 --- a/packages/webpack-cli/lib/utils/run-command.js +++ b/packages/webpack-cli/lib/utils/run-command.js @@ -1,11 +1,11 @@ const execa = require('execa'); -const logger = require('./logger'); +const utils = require('./index'); async function runCommand(command, args = []) { try { await execa(command, args, { stdio: 'inherit', shell: true }); } catch (error) { - logger.error(error.message); + utils.logger.error(error.message); process.exit(2); } } diff --git a/packages/webpack-cli/lib/webpack-cli.js b/packages/webpack-cli/lib/webpack-cli.js index 0baf614ee13..8fb1ffdebbd 100644 --- a/packages/webpack-cli/lib/webpack-cli.js +++ b/packages/webpack-cli/lib/webpack-cli.js @@ -2,32 +2,21 @@ const fs = require('fs'); const path = require('path'); const { program } = require('commander'); -const getPkg = require('./utils/package-exists'); -const webpack = getPkg('webpack') ? require('webpack') : undefined; -const interpret = require('interpret'); -const rechoir = require('rechoir'); -const { distance } = require('fastest-levenshtein'); -const { options: coloretteOptions, yellow, cyan, green, bold } = require('colorette'); - -const logger = require('./utils/logger'); -const capitalizeFirstLetter = require('./utils/capitalize-first-letter'); -const CLIPlugin = require('./plugins/CLIPlugin'); -const promptInstallation = require('./utils/prompt-installation'); -const toKebabCase = require('./utils/to-kebab-case'); +const utils = require('./utils'); class WebpackCLI { constructor() { // Global - this.webpack = webpack; - this.logger = logger; - this.utils = { toKebabCase, getPkg, promptInstallation }; + this.webpack = require('webpack'); + this.logger = utils.logger; + this.utils = utils; // Initialize program this.program = program; this.program.name('webpack'); this.program.configureOutput({ - writeErr: logger.error, - outputError: (str, write) => write(`Error: ${capitalizeFirstLetter(str.replace(/^error:/, '').trim())}`), + writeErr: this.logger.error, + outputError: (str, write) => write(`Error: ${this.utils.capitalizeFirstLetter(str.replace(/^error:/, '').trim())}`), }); } @@ -72,7 +61,8 @@ class WebpackCLI { if (commandOptions.dependencies && commandOptions.dependencies.length > 0) { for (const dependency of commandOptions.dependencies) { - const isPkgExist = getPkg(dependency); + const { packageExists } = this.utils; + const isPkgExist = packageExists(dependency); if (isPkgExist) { continue; @@ -81,17 +71,19 @@ class WebpackCLI { continue; } + const { promptInstallation, colors } = this.utils; + try { await promptInstallation(dependency, () => { - logger.error( - `For using '${green(commandOptions.name.split(' ')[0])}' command you need to install: '${green( + this.logger.error( + `For using '${colors.green(commandOptions.name.split(' ')[0])}' command you need to install: '${colors.green( dependency, )}' package`, ); }); } catch (error) { - logger.error("Action Interrupted, use 'webpack-cli help' to see possible commands."); - logger.error(error); + this.logger.error("Action Interrupted, use 'webpack-cli help' to see possible commands."); + this.logger.error(error); process.exit(2); } } @@ -227,6 +219,10 @@ class WebpackCLI { } getBuiltInOptions() { + if (this.builtInOptionsCache) { + return this.builtInOptionsCache; + } + const minimumHelpFlags = [ 'config', 'config-name', @@ -417,7 +413,7 @@ class WebpackCLI { }) : []; - return [] + const options = [] .concat(builtInFlags.filter((builtInFlag) => !coreFlags.find((coreFlag) => builtInFlag.name === coreFlag.name))) .concat(coreFlags) .map((option) => { @@ -425,6 +421,10 @@ class WebpackCLI { return option; }); + + this.builtInOptionsCache = options; + + return options; } async run(args, parseOptions) { @@ -547,7 +547,7 @@ class WebpackCLI { if (isWatchCommandUsed) { if (typeof options.watch !== 'undefined') { - logger.warn( + this.logger.warn( `No need to use the ${ options.watch ? "'--watch, -w'" : "'--no-watch'" } option together with the 'watch' command, it does not make sense`, @@ -570,7 +570,7 @@ class WebpackCLI { const builtInExternalCommandInfo = externalBuiltInCommandsInfo.find( (externalBuiltInCommandInfo) => getCommandName(externalBuiltInCommandInfo.name) === commandName || - (typeof Array.isArray(externalBuiltInCommandInfo.alias) + (Array.isArray(externalBuiltInCommandInfo.alias) ? externalBuiltInCommandInfo.alias.includes(commandName) : externalBuiltInCommandInfo.alias === commandName), ); @@ -583,17 +583,19 @@ class WebpackCLI { pkg = commandName; } - if (pkg !== 'webpack-cli' && !getPkg(pkg)) { + if (pkg !== 'webpack-cli' && !this.utils.packageExists(pkg)) { if (!allowToInstall) { return; } + const { promptInstallation, colors } = this.utils; + try { pkg = await promptInstallation(pkg, () => { - logger.error(`For using this command you need to install: '${green(pkg)}' package`); + this.logger.error(`For using this command you need to install: '${colors.green(pkg)}' package`); }); } catch (error) { - logger.error(`Action Interrupted, use '${cyan('webpack-cli help')}' to see possible commands`); + this.logger.error(`Action Interrupted, use '${colors.cyan('webpack-cli help')}' to see possible commands`); process.exit(2); } } @@ -619,8 +621,8 @@ class WebpackCLI { await command.apply(this); } catch (error) { - logger.error(`Unable to load '${pkg}' command`); - logger.error(error); + this.logger.error(`Unable to load '${pkg}' command`); + this.logger.error(error); process.exit(2); } } @@ -657,14 +659,14 @@ class WebpackCLI { const command = findCommandByName(operand); if (!command) { - logger.error(`Can't find and load command '${operand}'`); - logger.error("Run 'webpack --help' to see available commands and options"); + this.logger.error(`Can't find and load command '${operand}'`); + this.logger.error("Run 'webpack --help' to see available commands and options"); process.exit(2); } command.options.forEach((option) => { - if (distance(name, option.long.slice(2)) < 3) { - logger.error(`Did you mean '--${option.name()}'?`); + if (this.utils.levenshtein.distance(name, option.long.slice(2)) < 3) { + this.logger.error(`Did you mean '--${option.name()}'?`); } }); } @@ -677,24 +679,25 @@ class WebpackCLI { // - commander.missingMandatoryOptionValue // - commander.optionMissingArgument - logger.error("Run 'webpack --help' to see available commands and options"); + this.logger.error("Run 'webpack --help' to see available commands and options"); process.exit(2); }); // Default `--color` and `--no-color` options + const cli = this; this.program.option('--color', 'Enable colors on console.'); this.program.on('option:color', function () { const { color } = this.opts(); - coloretteOptions.changed = true; - coloretteOptions.enabled = color; + cli.utils.colors.options.changed = true; + cli.utils.colors.options.enabled = color; }); this.program.option('--no-color', 'Disable colors on console.'); this.program.on('option:no-color', function () { const { color } = this.opts(); - coloretteOptions.changed = true; - coloretteOptions.enabled = color; + cli.utils.colors.options.changed = true; + cli.utils.colors.options.enabled = color; }); // Make `-v, --version` options @@ -714,8 +717,8 @@ class WebpackCLI { return; } - logger.error(`Unknown option '${possibleCommandName}'`); - logger.error("Run 'webpack --help' to see available commands and options"); + this.logger.error(`Unknown option '${possibleCommandName}'`); + this.logger.error("Run 'webpack --help' to see available commands and options"); process.exit(2); }); @@ -726,17 +729,17 @@ class WebpackCLI { const foundCommand = findCommandByName(possibleCommandName); if (!foundCommand) { - logger.error(`Unknown command '${possibleCommandName}'`); - logger.error("Run 'webpack --help' to see available commands and options"); + this.logger.error(`Unknown command '${possibleCommandName}'`); + this.logger.error("Run 'webpack --help' to see available commands and options"); process.exit(2); } try { const { name, version } = require(`${foundCommand.pkg}/package.json`); - logger.raw(`${name} ${version}`); + this.logger.raw(`${name} ${version}`); } catch (e) { - logger.error(`Error: External package '${foundCommand.pkg}' not found`); + this.logger.error(`Error: External package '${foundCommand.pkg}' not found`); process.exit(2); } } @@ -744,14 +747,14 @@ class WebpackCLI { const pkgJSON = require('../package.json'); - logger.raw(`webpack ${this.webpack.version}`); - logger.raw(`webpack-cli ${pkgJSON.version}`); + this.logger.raw(`webpack ${this.webpack.version}`); + this.logger.raw(`webpack-cli ${pkgJSON.version}`); - if (getPkg('webpack-dev-server')) { + if (this.utils.packageExists('webpack-dev-server')) { // eslint-disable-next-line const { version } = require('webpack-dev-server/package.json'); - logger.raw(`webpack-dev-server ${version}`); + this.logger.raw(`webpack-dev-server ${version}`); } process.exit(0); @@ -762,10 +765,12 @@ class WebpackCLI { ); const outputHelp = async (options, isVerbose, isHelpCommandSyntax, program) => { + const { bold } = this.utils.colors; + const outputIncorrectUsageOfHelp = () => { - logger.error('Incorrect use of help'); - logger.error("Please use: 'webpack help [command] [option]' | 'webpack [command] --help'"); - logger.error("Run 'webpack --help' to see available commands and options"); + this.logger.error('Incorrect use of help'); + this.logger.error("Please use: 'webpack help [command] [option]' | 'webpack [command] --help'"); + this.logger.error("Run 'webpack --help' to see available commands and options"); process.exit(2); }; @@ -786,7 +791,7 @@ class WebpackCLI { } if (isGlobalHelp) { - return `${parentCmdNames}${command.usage()}\n${bold( + return `${parentCmdNames}${command.usage()}\n${this.utils.colors.bold( 'Alternative usage to run commands:', )} ${parentCmdNames}[command] [options]`; } @@ -921,7 +926,7 @@ class WebpackCLI { const buildCommand = findCommandByName(getCommandName(buildCommandOptions.name)); - logger.raw(buildCommand.helpInformation()); + this.logger.raw(buildCommand.helpInformation()); } else { const name = options[0]; @@ -930,12 +935,12 @@ class WebpackCLI { const command = findCommandByName(name); if (!command) { - logger.error(`Can't find and load command '${name}'`); - logger.error("Run 'webpack --help' to see available commands and options"); + this.logger.error(`Can't find and load command '${name}'`); + this.logger.error("Run 'webpack --help' to see available commands and options"); process.exit(2); } - logger.raw(command.helpInformation()); + this.logger.raw(command.helpInformation()); } } else if (isHelpCommandSyntax) { let isCommandSpecified = false; @@ -961,16 +966,16 @@ class WebpackCLI { const command = isGlobalOption(optionName) ? program : findCommandByName(commandName); if (!command) { - logger.error(`Can't find and load command '${commandName}'`); - logger.error("Run 'webpack --help' to see available commands and options"); + this.logger.error(`Can't find and load command '${commandName}'`); + this.logger.error("Run 'webpack --help' to see available commands and options"); process.exit(2); } const option = command.options.find((option) => option.short === optionName || option.long === optionName); if (!option) { - logger.error(`Unknown option '${optionName}'`); - logger.error("Run 'webpack --help' to see available commands and options"); + this.logger.error(`Unknown option '${optionName}'`); + this.logger.error("Run 'webpack --help' to see available commands and options"); process.exit(2); } @@ -978,12 +983,12 @@ class WebpackCLI { option.flags.replace(/^.+[[<]/, '').replace(/(\.\.\.)?[\]>].*$/, '') + (option.variadic === true ? '...' : ''); const value = option.required ? '<' + nameOutput + '>' : option.optional ? '[' + nameOutput + ']' : ''; - logger.raw( + this.logger.raw( `${bold('Usage')}: webpack${isCommandSpecified ? ` ${commandName}` : ''} ${option.long}${value ? ` ${value}` : ''}`, ); if (option.short) { - logger.raw( + this.logger.raw( `${bold('Short:')} webpack${isCommandSpecified ? ` ${commandName}` : ''} ${option.short}${ value ? ` ${value}` : '' }`, @@ -991,14 +996,14 @@ class WebpackCLI { } if (option.description) { - logger.raw(`${bold('Description:')} ${option.description}`); + this.logger.raw(`${bold('Description:')} ${option.description}`); } if (!option.negate && options.defaultValue) { - logger.raw(`${bold('Default value:')} ${JSON.stringify(option.defaultValue)}`); + this.logger.raw(`${bold('Default value:')} ${JSON.stringify(option.defaultValue)}`); } - logger.raw(''); + this.logger.raw(''); // TODO implement this after refactor cli arguments // logger.raw('Possible values: foo | bar'); @@ -1007,10 +1012,10 @@ class WebpackCLI { outputIncorrectUsageOfHelp(); } - logger.raw("To see list of all supported commands and options run 'webpack --help=verbose'.\n"); - logger.raw(`${bold('Webpack documentation:')} https://webpack.js.org/.`); - logger.raw(`${bold('CLI documentation:')} https://webpack.js.org/api/cli/.`); - logger.raw(`${bold('Made with ♥ by the webpack team')}.`); + this.logger.raw("To see list of all supported commands and options run 'webpack --help=verbose'.\n"); + this.logger.raw(`${bold('Webpack documentation:')} https://webpack.js.org/.`); + this.logger.raw(`${bold('CLI documentation:')} https://webpack.js.org/api/cli/.`); + this.logger.raw(`${bold('Made with ♥ by the webpack team')}.`); process.exit(0); }; this.program.helpOption(false); @@ -1026,7 +1031,7 @@ class WebpackCLI { if (!isInternalActionCalled) { isInternalActionCalled = true; } else { - logger.error('No commands found to run'); + this.logger.error('No commands found to run'); process.exit(2); } @@ -1044,7 +1049,7 @@ class WebpackCLI { if (options.help) { if (typeof options.help === 'string') { if (options.help !== 'verbose') { - logger.error("Unknown value for '--help' option, please use '--help=verbose'"); + this.logger.error("Unknown value for '--help' option, please use '--help=verbose'"); process.exit(2); } @@ -1081,13 +1086,7 @@ class WebpackCLI { if (isKnownCommand(commandToRun)) { await loadCommandByName(commandToRun, true); } else { - let isEntrySyntax = true; - - try { - await fs.promises.access(operand, fs.constants.F_OK); - } catch (error) { - isEntrySyntax = false; - } + let isEntrySyntax = fs.existsSync(operand); if (isEntrySyntax) { commandToRun = defaultCommandToRun; @@ -1095,19 +1094,21 @@ class WebpackCLI { await loadCommandByName(commandToRun); } else { - logger.error(`Unknown command or entry '${operand}'`); + this.logger.error(`Unknown command or entry '${operand}'`); - const found = knownCommands.find((commandOptions) => distance(operand, getCommandName(commandOptions.name)) < 3); + const found = knownCommands.find( + (commandOptions) => this.utils.levenshtein.distance(operand, getCommandName(commandOptions.name)) < 3, + ); if (found) { - logger.error( + this.logger.error( `Did you mean '${getCommandName(found.name)}' (alias '${ Array.isArray(found.alias) ? found.alias.join(', ') : found.alias }')?`, ); } - logger.error("Run 'webpack --help' to see available commands and options"); + this.logger.error("Run 'webpack --help' to see available commands and options"); process.exit(2); } } @@ -1120,25 +1121,28 @@ class WebpackCLI { async resolveConfig(options) { const loadConfig = async (configPath) => { + const { interpret } = this.utils; const ext = path.extname(configPath); const interpreted = Object.keys(interpret.jsVariants).find((variant) => variant === ext); if (interpreted) { + const { rechoir } = this.utils; + try { rechoir.prepare(interpret.extensions, configPath); } catch (error) { if (error.failures) { - logger.error(`Unable load '${configPath}'`); - logger.error(error.message); + this.logger.error(`Unable load '${configPath}'`); + this.logger.error(error.message); error.failures.forEach((failure) => { - logger.error(failure.error.message); + this.logger.error(failure.error.message); }); - logger.error('Please install one of them'); + this.logger.error('Please install one of them'); process.exit(2); } - logger.error(error); + this.logger.error(error); process.exit(2); } } @@ -1171,12 +1175,12 @@ class WebpackCLI { throw error; } } catch (error) { - logger.error(`Failed to load '${configPath}' config`); + this.logger.error(`Failed to load '${configPath}' config`); if (this.isValidationError(error)) { - logger.error(error.message); + this.logger.error(error.message); } else { - logger.error(error); + this.logger.error(error); } process.exit(2); @@ -1214,7 +1218,7 @@ class WebpackCLI { const isObject = (value) => typeof value === 'object' && value !== null; if (!isObject(loadedConfig.options) && !Array.isArray(loadedConfig.options)) { - logger.error(`Invalid configuration in '${loadedConfig.path}'`); + this.logger.error(`Invalid configuration in '${loadedConfig.path}'`); process.exit(2); } @@ -1244,6 +1248,8 @@ class WebpackCLI { config.options = config.options.length === 1 ? config.options[0] : config.options; } else { + const { interpret } = this.utils; + // Order defines the priority, in increasing order const defaultConfigFiles = ['webpack.config', '.webpack/webpack.config', '.webpack/webpackfile'] .map((filename) => @@ -1259,9 +1265,7 @@ class WebpackCLI { let foundDefaultConfigFile; for (const defaultConfigFile of defaultConfigFiles) { - try { - await fs.promises.access(defaultConfigFile.path, fs.constants.F_OK); - } catch (error) { + if (!fs.existsSync(defaultConfigFile.path)) { continue; } @@ -1305,7 +1309,7 @@ class WebpackCLI { }); if (notfoundConfigNames.length > 0) { - logger.error( + this.logger.error( notfoundConfigNames.map((configName) => `Configuration with the name "${configName}" was not found.`).join(' '), ); process.exit(2); @@ -1319,7 +1323,7 @@ class WebpackCLI { // either by passing multiple configs by flags or passing a // single config exporting an array if (!Array.isArray(config.options) || config.options.length <= 1) { - logger.error('At least two configurations are required for merge.'); + this.logger.error('At least two configurations are required for merge.'); process.exit(2); } @@ -1342,22 +1346,26 @@ class WebpackCLI { // TODO refactor async applyOptions(config, options) { if (options.analyze) { - if (!getPkg('webpack-bundle-analyzer')) { + if (!this.utils.packageExists('webpack-bundle-analyzer')) { + const { promptInstallation, colors } = this.utils; + try { await promptInstallation('webpack-bundle-analyzer', () => { - logger.error(`It looks like ${yellow('webpack-bundle-analyzer')} is not installed.`); + this.logger.error(`It looks like ${colors.yellow('webpack-bundle-analyzer')} is not installed.`); }); } catch (error) { - logger.error(`Action Interrupted, Please try once again or install ${yellow('webpack-bundle-analyzer')} manually.`); + this.logger.error( + `Action Interrupted, Please try once again or install ${colors.yellow('webpack-bundle-analyzer')} manually.`, + ); process.exit(2); } - logger.success(`${yellow('webpack-bundle-analyzer')} was installed successfully.`); + this.logger.success(`${colors.yellow('webpack-bundle-analyzer')} was installed successfully.`); } } if (typeof options.progress === 'string' && options.progress !== 'profile') { - logger.error(`'${options.progress}' is an invalid value for the --progress option. Only 'profile' is allowed.`); + this.logger.error(`'${options.progress}' is an invalid value for the --progress option. Only 'profile' is allowed.`); process.exit(2); } @@ -1376,7 +1384,7 @@ class WebpackCLI { return accumulator; } - const kebabName = toKebabCase(name); + const kebabName = this.utils.toKebabCase(name); if (args[kebabName]) { accumulator[kebabName] = options[name]; @@ -1401,14 +1409,14 @@ class WebpackCLI { const problems = problemsByPath[path]; problems.forEach((problem) => { - logger.error( - `${capitalizeFirstLetter(problem.type.replace(/-/g, ' '))}${ + this.logger.error( + `${this.utils.capitalizeFirstLetter(problem.type.replace(/-/g, ' '))}${ problem.value ? ` '${problem.value}'` : '' } for the '--${problem.argument}' option${problem.index ? ` by index '${problem.index}'` : ''}`, ); if (problem.expected) { - logger.error(`Expected: '${problem.expected}'`); + this.logger.error(`Expected: '${problem.expected}'`); } }); } @@ -1550,8 +1558,8 @@ class WebpackCLI { let colors; // From arguments - if (typeof coloretteOptions.changed !== 'undefined') { - colors = Boolean(coloretteOptions.enabled); + if (typeof this.utils.colors.options.changed !== 'undefined') { + colors = Boolean(this.utils.colors.options.enabled); } // From stats else if (typeof configOptions.stats.colors !== 'undefined') { @@ -1559,7 +1567,7 @@ class WebpackCLI { } // Default else { - colors = Boolean(coloretteOptions.enabled); + colors = Boolean(this.utils.colors.options.enabled); } configOptions.stats.colors = colors; @@ -1580,6 +1588,8 @@ class WebpackCLI { configOptions.plugins = []; } + const CLIPlugin = require('./plugins/CLIPlugin'); + configOptions.plugins.unshift( new CLIPlugin({ configPath: config.path, @@ -1630,7 +1640,7 @@ class WebpackCLI { callback ? (error, stats) => { if (error && this.isValidationError(error)) { - logger.error(error.message); + this.logger.error(error.message); process.exit(2); } @@ -1640,9 +1650,9 @@ class WebpackCLI { ); } catch (error) { if (this.isValidationError(error)) { - logger.error(error.message); + this.logger.error(error.message); } else { - logger.error(error); + this.logger.error(error); } process.exit(2); @@ -1661,7 +1671,7 @@ class WebpackCLI { const callback = (error, stats) => { if (error) { - logger.error(error); + this.logger.error(error); process.exit(2); } @@ -1689,7 +1699,7 @@ class WebpackCLI { if (options.json) { const { stringifyStream: createJsonStringifyStream } = require('@discoveryjs/json-ext'); const handleWriteError = (error) => { - logger.error(error); + this.logger.error(error); process.exit(2); }; @@ -1706,7 +1716,9 @@ class WebpackCLI { .on('error', handleWriteError) // Use stderr to logging .on('close', () => - process.stderr.write(`[webpack-cli] ${green(`stats are successfully stored as json to ${options.json}`)}\n`), + process.stderr.write( + `[webpack-cli] ${this.utils.colors.green(`stats are successfully stored as json to ${options.json}`)}\n`, + ), ); } } else { @@ -1714,7 +1726,7 @@ class WebpackCLI { // Avoid extra empty line when `stats: 'none'` if (printedStats) { - logger.raw(printedStats); + this.logger.raw(printedStats); } } }; From ed76f9b0e8db8a146adf40802a422adadd1a6c9b Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 29 Jan 2021 18:39:01 +0300 Subject: [PATCH 14/29] chore(deps-dev): bump ts-jest from 26.4.4 to 26.5.0 (#2383) Bumps [ts-jest](https://github.com/kulshekhar/ts-jest) from 26.4.4 to 26.5.0. - [Release notes](https://github.com/kulshekhar/ts-jest/releases) - [Changelog](https://github.com/kulshekhar/ts-jest/blob/master/CHANGELOG.md) - [Commits](https://github.com/kulshekhar/ts-jest/compare/v26.4.4...v26.5.0) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- yarn.lock | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/yarn.lock b/yarn.lock index a05832ed73a..b807d3bb3f8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7302,11 +7302,6 @@ lodash.ismatch@^4.4.0: resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37" integrity sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc= -lodash.memoize@4.x: - version "4.1.2" - resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= - lodash.set@^4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23" @@ -7337,7 +7332,7 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.4, lodash@^4.2.1: +lodash@4.x, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.4, lodash@^4.2.1: version "4.17.20" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== @@ -10587,9 +10582,9 @@ trim-off-newlines@^1.0.0: integrity sha1-n5up2e+odkw4dpi8v+sshI8RrbM= ts-jest@^26.4.3: - version "26.4.4" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-26.4.4.tgz#61f13fb21ab400853c532270e52cc0ed7e502c49" - integrity sha512-3lFWKbLxJm34QxyVNNCgXX1u4o/RV0myvA2y2Bxm46iGIjKlaY0own9gIckbjZJPn+WaJEnfPPJ20HHGpoq4yg== + version "26.5.0" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-26.5.0.tgz#3e3417d91bc40178a6716d7dacc5b0505835aa21" + integrity sha512-Ya4IQgvIFNa2Mgq52KaO8yBw2W8tWp61Ecl66VjF0f5JaV8u50nGoptHVILOPGoI7SDnShmEqnYQEmyHdQ+56g== dependencies: "@types/jest" "26.x" bs-logger "0.x" @@ -10597,7 +10592,7 @@ ts-jest@^26.4.3: fast-json-stable-stringify "2.x" jest-util "^26.1.0" json5 "2.x" - lodash.memoize "4.x" + lodash "4.x" make-error "1.x" mkdirp "1.x" semver "7.x" From dcb452ebb6630056611f084dfe4db07cd32d4625 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sat, 30 Jan 2021 15:48:19 +0300 Subject: [PATCH 15/29] chore(deps-dev): bump webpack from 5.18.0 to 5.19.0 (#2384) Bumps [webpack](https://github.com/webpack/webpack) from 5.18.0 to 5.19.0. - [Release notes](https://github.com/webpack/webpack/releases) - [Commits](https://github.com/webpack/webpack/compare/v5.18.0...v5.19.0) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index b807d3bb3f8..d99f9a919b7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11073,9 +11073,9 @@ webpack-sources@^2.1.1: source-map "^0.6.1" webpack@^5.18.0: - version "5.18.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.18.0.tgz#bbcf13094aa0da0534d513f27d7ee72d74e499c6" - integrity sha512-RmiP/iy6ROvVe/S+u0TrvL/oOmvP+2+Bs8MWjvBwwY/j82Q51XJyDJ75m0QAGntL1Wx6B//Xc0+4VPP/hlNHmw== + version "5.19.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.19.0.tgz#1a5fee84dd63557e68336b0774ac4a1c81aa2c73" + integrity sha512-egX19vAQ8fZ4cVYtA9Y941eqJtcZAK68mQq87MMv+GTXKZOc3TpKBBxdGX+HXUYlquPxiluNsJ1VHvwwklW7CQ== dependencies: "@types/eslint-scope" "^3.7.0" "@types/estree" "^0.0.46" From 710e343b0a791ba94d4544bba6f5a59c1550a84d Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sun, 31 Jan 2021 17:12:16 +0300 Subject: [PATCH 16/29] chore(deps-dev): bump eslint from 7.18.0 to 7.19.0 (#2387) Bumps [eslint](https://github.com/eslint/eslint) from 7.18.0 to 7.19.0. - [Release notes](https://github.com/eslint/eslint/releases) - [Changelog](https://github.com/eslint/eslint/blob/master/CHANGELOG.md) - [Commits](https://github.com/eslint/eslint/compare/v7.18.0...v7.19.0) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index d99f9a919b7..570916aea85 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4408,9 +4408,9 @@ eslint-visitor-keys@^2.0.0: integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== eslint@^7.12.1: - version "7.18.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.18.0.tgz#7fdcd2f3715a41fe6295a16234bd69aed2c75e67" - integrity sha512-fbgTiE8BfUJZuBeq2Yi7J3RB3WGUQ9PNuNbmgi6jt9Iv8qrkxfy19Ds3OpL1Pm7zg3BtTVhvcUZbIRQ0wmSjAQ== + version "7.19.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.19.0.tgz#6719621b196b5fad72e43387981314e5d0dc3f41" + integrity sha512-CGlMgJY56JZ9ZSYhJuhow61lMPPjUzWmChFya71Z/jilVos7mR/jPgaEfVGgMBY5DshbKdG8Ezb8FDCHcoMEMg== dependencies: "@babel/code-frame" "^7.0.0" "@eslint/eslintrc" "^0.3.0" From 2c85b9b6a97a6c9c72b4ec74fdaafd67e2ef1627 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sun, 31 Jan 2021 17:12:25 +0300 Subject: [PATCH 17/29] chore(deps): bump yeoman-generator from 4.12.0 to 4.13.0 (#2386) Bumps [yeoman-generator](https://github.com/yeoman/generator) from 4.12.0 to 4.13.0. - [Release notes](https://github.com/yeoman/generator/releases) - [Commits](https://github.com/yeoman/generator/compare/v4.12.0...v4.13.0) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- yarn.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/yarn.lock b/yarn.lock index 570916aea85..c787ad26d6f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9710,7 +9710,7 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -shelljs@^0.8.3: +shelljs@^0.8.4: version "0.8.4" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.4.tgz#de7684feeb767f8716b326078a8a00875890e3c2" integrity sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ== @@ -11447,9 +11447,9 @@ yeoman-environment@^2.10.0, yeoman-environment@^2.10.3, yeoman-environment@^2.9. yeoman-generator "^4.8.2" yeoman-generator@^4.10.0, yeoman-generator@^4.12.0, yeoman-generator@^4.8.2: - version "4.12.0" - resolved "https://registry.yarnpkg.com/yeoman-generator/-/yeoman-generator-4.12.0.tgz#512e783a38b004c49265e71826a09ff7f1939f4b" - integrity sha512-lozwklVQHwUXMM1o8BgxEB8F5BB7vkHW4pjAo1Zt5sJ7FOlWhd6DJ4ZxJ2OK0w+gNYkY/ocPMkUV7DTz/uqEEg== + version "4.13.0" + resolved "https://registry.yarnpkg.com/yeoman-generator/-/yeoman-generator-4.13.0.tgz#a6caeed8491fceea1f84f53e31795f25888b4672" + integrity sha512-f2/5N5IR3M2Ozm+QocvZQudlQITv2DwI6Mcxfy7R7gTTzaKgvUpgo/pQMJ+WQKm0KN0YMWCFOZpj0xFGxevc1w== dependencies: async "^2.6.2" chalk "^2.4.2" @@ -11473,7 +11473,7 @@ yeoman-generator@^4.10.0, yeoman-generator@^4.12.0, yeoman-generator@^4.8.2: rimraf "^2.6.3" run-async "^2.0.0" semver "^7.2.1" - shelljs "^0.8.3" + shelljs "^0.8.4" text-table "^0.2.0" through2 "^3.0.1" optionalDependencies: From 9d6dbda93da167a1aaad03f599105a4fe7849dc3 Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Sun, 31 Jan 2021 20:04:13 +0530 Subject: [PATCH 18/29] fix: avoid deprecation message --- packages/serve/src/index.ts | 2 +- packages/webpack-cli/lib/webpack-cli.js | 56 +++++++++---- test/serve/basic/serve-basic.test.js | 28 ++++++- test/serve/basic/watch.config.js | 8 ++ test/watch/basic/basic.test.js | 65 +++++---------- test/watch/watch-variable/src/index.js | 1 + .../watch-variable/watch-variable.test.js | 81 +++++++++++++++++++ test/watch/watch-variable/webpack.config.js | 24 ++++++ 8 files changed, 202 insertions(+), 63 deletions(-) create mode 100644 test/serve/basic/watch.config.js create mode 100644 test/watch/watch-variable/src/index.js create mode 100644 test/watch/watch-variable/watch-variable.test.js create mode 100644 test/watch/watch-variable/webpack.config.js diff --git a/packages/serve/src/index.ts b/packages/serve/src/index.ts index 508b5cee234..8b52e1568ec 100644 --- a/packages/serve/src/index.ts +++ b/packages/serve/src/index.ts @@ -24,7 +24,7 @@ class ServeCommand { process.exit(2); } - const builtInOptions = cli.getBuiltInOptions(); + const builtInOptions = cli.getBuiltInOptions().filter((option) => option.name !== 'watch'); return [...builtInOptions, ...devServerFlags]; }, diff --git a/packages/webpack-cli/lib/webpack-cli.js b/packages/webpack-cli/lib/webpack-cli.js index 8fb1ffdebbd..04d28a9135e 100644 --- a/packages/webpack-cli/lib/webpack-cli.js +++ b/packages/webpack-cli/lib/webpack-cli.js @@ -537,27 +537,17 @@ class WebpackCLI { const isWatchCommandUsed = isCommand(commandName, watchCommandOptions); if (isBuildCommandUsed || isWatchCommandUsed) { + const options = this.getBuiltInOptions(); + await this.makeCommand( isBuildCommandUsed ? buildCommandOptions : watchCommandOptions, - this.getBuiltInOptions(), + isWatchCommandUsed ? options.filter((option) => option.name !== 'watch') : options, async (entries, options) => { if (entries.length > 0) { options.entry = [...entries, ...(options.entry || [])]; } - if (isWatchCommandUsed) { - if (typeof options.watch !== 'undefined') { - this.logger.warn( - `No need to use the ${ - options.watch ? "'--watch, -w'" : "'--no-watch'" - } option together with the 'watch' command, it does not make sense`, - ); - } - - options.watch = true; - } - - await this.buildCommand(options); + await this.buildCommand(options, isWatchCommandUsed); }, ); } else if (isCommand(commandName, helpCommandOptions)) { @@ -1369,6 +1359,31 @@ class WebpackCLI { process.exit(2); } + const outputHints = (configOptions) => { + if ( + configOptions.watch && + options.argv && + options.argv.env && + (options.argv.env['WEBPACK_WATCH'] || options.argv.env['WEBPACK_SERVE']) + ) { + this.logger.warn( + `No need to use the '${ + options.argv.env['WEBPACK_WATCH'] ? 'watch' : 'serve' + }' command together with '{ watch: true }' configuration, it does not make sense.`, + ); + + if (options.argv.env['WEBPACK_SERVE']) { + configOptions.watch = false; + } + } + + return configOptions; + }; + + config.options = Array.isArray(config.options) + ? config.options.map((options) => outputHints(options)) + : outputHints(config.options); + if (this.webpack.cli) { const processArguments = (configOptions) => { const args = this.getBuiltInOptions() @@ -1666,7 +1681,7 @@ class WebpackCLI { return compiler; } - async buildCommand(options) { + async buildCommand(options, isWatchCommand) { let compiler; const callback = (error, stats) => { @@ -1731,7 +1746,16 @@ class WebpackCLI { } }; - options.argv = { ...options, env: { WEBPACK_BUNDLE: true, WEBPACK_BUILD: true, ...options.env } }; + const env = + isWatchCommand || options.watch + ? { WEBPACK_WATCH: true, ...options.env } + : { WEBPACK_BUNDLE: true, WEBPACK_BUILD: true, ...options.env }; + + options.argv = { ...options, env }; + + if (isWatchCommand) { + options.watch = true; + } compiler = await this.createCompiler(options, callback); diff --git a/test/serve/basic/serve-basic.test.js b/test/serve/basic/serve-basic.test.js index a57308f0a00..d215cea596e 100644 --- a/test/serve/basic/serve-basic.test.js +++ b/test/serve/basic/serve-basic.test.js @@ -296,7 +296,33 @@ describe('basic serve usage', () => { expect(stdout.match(/HotModuleReplacementPlugin/g)).toBeNull(); }); - it('should log and error on unknown flag', async () => { + it('should work and log warning on the `watch option in a configuration', async () => { + const { stderr, stdout } = await runServe(__dirname, ['--config', './watch.config.js', '--port', port]); + + expect(stderr).toContain( + "No need to use the 'serve' command together with '{ watch: true }' configuration, it does not make sense.", + ); + expect(stdout).toContain('development'); + expect(stdout.match(/HotModuleReplacementPlugin/g)).toBeNull(); + }); + + it("should log error on using '--watch' flag with serve", async () => { + const { stdout, stderr } = await runServe(testPath, ['--watch']); + + expect(stderr).toContain("Error: Unknown option '--watch'"); + expect(stderr).toContain("Run 'webpack --help' to see available commands and options"); + expect(stdout).toBeFalsy(); + }); + + it("should log error on using '-w' alias with serve", async () => { + const { stdout, stderr } = await runServe(testPath, ['-w']); + + expect(stderr).toContain("Error: Unknown option '-w'"); + expect(stderr).toContain("Run 'webpack --help' to see available commands and options"); + expect(stdout).toBeFalsy(); + }); + + it('should log an error on unknown flag', async () => { const { exitCode, stdout, stderr } = await runServe(testPath, ['--port', port, '--unknown-flag']); expect(exitCode).toBe(2); diff --git a/test/serve/basic/watch.config.js b/test/serve/basic/watch.config.js new file mode 100644 index 00000000000..7f7eb3153b8 --- /dev/null +++ b/test/serve/basic/watch.config.js @@ -0,0 +1,8 @@ +const WebpackCLITestPlugin = require('../../utils/webpack-cli-test-plugin'); + +module.exports = { + mode: 'development', + devtool: false, + plugins: [new WebpackCLITestPlugin(['mode'], false, 'hooks.compilation.taps')], + watch: true, +}; diff --git a/test/watch/basic/basic.test.js b/test/watch/basic/basic.test.js index 0d24c6dda3a..771e4f81344 100644 --- a/test/watch/basic/basic.test.js +++ b/test/watch/basic/basic.test.js @@ -5,7 +5,7 @@ const { run, runAndGetWatchProc, isWebpack5 } = require('../../utils/test-utils' const { writeFileSync } = require('fs'); const { resolve } = require('path'); -const wordsInStatsv4 = ['Hash', 'Version', 'Time', 'Built at:', 'main.js']; +const wordsInStatsv4 = ['Hash', 'Built at:', 'main.js']; const wordsInStatsv5 = ['asset', 'index.js', 'compiled successfully']; describe('basic', () => { @@ -118,11 +118,10 @@ describe('basic', () => { }); }); - it('should recompile upon file change using the `command` option and the `--watch` option and log warning', (done) => { - const proc = runAndGetWatchProc(__dirname, ['watch', '--watch', '--mode', 'development'], false, '', true); + it('should log warning about the `watch` option in the configuration and recompile upon file change using the `watch` command', (done) => { + const proc = runAndGetWatchProc(__dirname, ['--watch', '--mode', 'development', '--config', './watch.config.js'], false, '', true); let modified = false; - let hasWarning = false; proc.stdout.on('data', (chunk) => { const data = stripAnsi(chunk.toString()); @@ -138,7 +137,7 @@ describe('basic', () => { } } - if (!modified && !hasWarning) { + if (!modified) { process.nextTick(() => { writeFileSync(resolve(__dirname, './src/index.js'), `console.log('watch flag test');`); }); @@ -154,51 +153,27 @@ describe('basic', () => { proc.stderr.on('data', (chunk) => { const data = stripAnsi(chunk.toString()); - hasWarning = true; - - expect(data).toContain("No need to use the '--watch, -w' option together with the 'watch' command, it does not make sense"); + expect(data).toContain( + "No need to use the 'watch' command together with '{ watch: true }' configuration, it does not make sense.", + ); }); }); - it('should recompile upon file change using the `command` option and the `--no-watch` option and log warning', (done) => { - const proc = runAndGetWatchProc(__dirname, ['watch', '--no-watch', '--mode', 'development'], false, '', true); - - let modified = false; - let hasWarning = false; - - proc.stdout.on('data', (chunk) => { - const data = stripAnsi(chunk.toString()); - - if (data.includes('index.js')) { - if (isWebpack5) { - for (const word of wordsInStatsv5) { - expect(data).toContain(word); - } - } else { - for (const word of wordsInStatsv4) { - expect(data).toContain(word); - } - } - - if (!modified && !hasWarning) { - process.nextTick(() => { - writeFileSync(resolve(__dirname, './src/index.js'), `console.log('watch flag test');`); - }); + it('should recompile upon file change using the `command` option and the `--watch` option and log warning', async () => { + const { exitCode, stderr, stdout } = await run(__dirname, ['watch', '--watch', '--mode', 'development']); - modified = true; - } else { - proc.kill(); - done(); - } - } - }); - - proc.stderr.on('data', (chunk) => { - const data = stripAnsi(chunk.toString()); + expect(exitCode).toBe(2); + expect(stderr).toContain("Error: Unknown option '--watch'"); + expect(stderr).toContain("Run 'webpack --help' to see available commands and options"); + expect(stdout).toBeFalsy(); + }); - hasWarning = true; + it('should recompile upon file change using the `command` option and the `--no-watch` option and log warning', async () => { + const { exitCode, stderr, stdout } = await run(__dirname, ['watch', '--no-watch', '--mode', 'development']); - expect(data).toContain("No need to use the '--no-watch' option together with the 'watch' command, it does not make sense"); - }); + expect(exitCode).toBe(2); + expect(stderr).toContain("Error: Unknown option '--no-watch'"); + expect(stderr).toContain("Run 'webpack --help' to see available commands and options"); + expect(stdout).toBeFalsy(); }); }); diff --git a/test/watch/watch-variable/src/index.js b/test/watch/watch-variable/src/index.js new file mode 100644 index 00000000000..efc51ca0a97 --- /dev/null +++ b/test/watch/watch-variable/src/index.js @@ -0,0 +1 @@ +console.log('watch flag test'); \ No newline at end of file diff --git a/test/watch/watch-variable/watch-variable.test.js b/test/watch/watch-variable/watch-variable.test.js new file mode 100644 index 00000000000..0f5cc994ed6 --- /dev/null +++ b/test/watch/watch-variable/watch-variable.test.js @@ -0,0 +1,81 @@ +'use strict'; + +const stripAnsi = require('strip-ansi'); +const { runAndGetWatchProc, isWebpack5 } = require('../../utils/test-utils'); +const { writeFileSync } = require('fs'); +const { resolve } = require('path'); + +const wordsInStatsv4 = ['Hash', 'Built at:', 'main.js']; +const wordsInStatsv5 = ['asset', 'index.js', 'compiled successfully']; + +describe('watch variable', () => { + it('should pass `WEBPACK_WATCH` env variable and recompile upon file change using the `watch` command', (done) => { + const proc = runAndGetWatchProc(__dirname, ['watch', '--mode', 'development'], false, '', true); + + let modified = false; + + proc.stdout.on('data', (chunk) => { + const data = stripAnsi(chunk.toString()); + + expect(data).not.toContain('FAIL'); + + if (data.includes('index.js')) { + if (isWebpack5) { + for (const word of wordsInStatsv5) { + expect(data).toContain(word); + } + } else { + for (const word of wordsInStatsv4) { + expect(data).toContain(word); + } + } + + if (!modified) { + process.nextTick(() => { + writeFileSync(resolve(__dirname, './src/index.js'), `console.log('watch flag test');`); + }); + + modified = true; + } else { + proc.kill(); + done(); + } + } + }); + }); + + it('should pass `WEBPACK_WATCH` env variable and recompile upon file change using the `--watch` option', (done) => { + const proc = runAndGetWatchProc(__dirname, ['--watch', '--mode', 'development'], false, '', true); + + let modified = false; + + proc.stdout.on('data', (chunk) => { + const data = stripAnsi(chunk.toString()); + + expect(data).not.toContain('FAIL'); + + if (data.includes('index.js')) { + if (isWebpack5) { + for (const word of wordsInStatsv5) { + expect(data).toContain(word); + } + } else { + for (const word of wordsInStatsv4) { + expect(data).toContain(word); + } + } + + if (!modified) { + process.nextTick(() => { + writeFileSync(resolve(__dirname, './src/index.js'), `console.log('watch flag test');`); + }); + + modified = true; + } else { + proc.kill(); + done(); + } + } + }); + }); +}); diff --git a/test/watch/watch-variable/webpack.config.js b/test/watch/watch-variable/webpack.config.js new file mode 100644 index 00000000000..a177e2cf731 --- /dev/null +++ b/test/watch/watch-variable/webpack.config.js @@ -0,0 +1,24 @@ +const isInProcess = process.env.WEBPACK_WATCH; + +class CustomTestPlugin { + constructor(isInEnvironment) { + this.isInEnvironment = isInEnvironment; + } + apply(compiler) { + compiler.hooks.done.tap('testPlugin', () => { + if (!isInProcess && this.isInEnvironment) { + console.log('PASS'); + } else { + console.log('FAIL'); + } + }); + } +} + +module.exports = (env) => { + return { + mode: 'development', + devtool: false, + plugins: [new CustomTestPlugin(env.WEBPACK_WATCH)], + }; +}; From 7092a724d07462205fe3612baa2e27b0d744d7fb Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Mon, 1 Feb 2021 15:28:49 +0530 Subject: [PATCH 19/29] chore: remove git-cz (#2389) --- .github/CONTRIBUTING.md | 2 -- package.json | 2 -- yarn.lock | 5 ----- 3 files changed, 9 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index c32b815ef98..d7d77e2a22d 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -193,8 +193,6 @@ In case you've got a small change in most of the cases, your pull request would Our commit messages format follows the [angular.js commits format](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#commits). -You can use `yarn commit` script to have an interactive way of making commits that follow our guidelines. - We don't use the scope. The template of a commit would look like this: ### Commit Message Format diff --git a/package.json b/package.json index 504d74f5ff9..a54dc077679 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,6 @@ "build": "tsc --build", "build:ci": "tsc --build", "watch": "tsc --build --watch", - "commit": "git-cz", "lint:prettier": "prettier --list-different . \"!**/*.{js,ts}\" ", "lint:eslint": "eslint --cache --ext .js --ext .ts .", "lint": "yarn lint:eslint && yarn lint:prettier", @@ -77,7 +76,6 @@ "eslint-plugin-prettier": "^3.1.4", "execa": "^5.0.0", "get-port": "^5.1.1", - "git-cz": "^4.7.1", "husky": "^4.3.0", "jest": "^26.6.1", "jest-serializer-ansi": "^1.0.3", diff --git a/yarn.lock b/yarn.lock index c787ad26d6f..2d97813f88f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5209,11 +5209,6 @@ gh-got@^5.0.0: got "^6.2.0" is-plain-obj "^1.1.0" -git-cz@^4.7.1: - version "4.7.6" - resolved "https://registry.yarnpkg.com/git-cz/-/git-cz-4.7.6.tgz#1250c486f01724e801a630b848fd8786f7e67e90" - integrity sha512-WtQEXqetJSi9LKPI77bMdSQWvLGjE93egVbR0zjXd1KFKrFvo/YE/UuGNcMeBDiwzxfQBhjyV7Hn0YUZ8Q0BcQ== - git-raw-commits@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-2.0.0.tgz#d92addf74440c14bcc5c83ecce3fb7f8a79118b5" From 7bd747a4815136d90c812c0fd9ae8c231556fadb Mon Sep 17 00:00:00 2001 From: James George Date: Mon, 1 Feb 2021 16:00:20 +0530 Subject: [PATCH 20/29] chore(init): remove --force flag (#2391) --- INIT.md | 6 -- .../src/utils/modify-config-helper.ts | 3 +- packages/generators/src/utils/scaffold.ts | 6 +- packages/init/README.md | 6 -- packages/init/src/index.ts | 7 +-- test/init/force/init-force.test.js | 60 ------------------- 6 files changed, 3 insertions(+), 85 deletions(-) delete mode 100644 test/init/force/init-force.test.js diff --git a/INIT.md b/INIT.md index fed6af945fd..94769b34572 100644 --- a/INIT.md +++ b/INIT.md @@ -81,12 +81,6 @@ webpack-cli init webpack-cli init --auto ``` -**To force config generation** - -```bash -webpack-cli init --force -``` - **To scaffold in a specified path** ```bash diff --git a/packages/generators/src/utils/modify-config-helper.ts b/packages/generators/src/utils/modify-config-helper.ts index 09f9d23f8b4..8dede3af614 100644 --- a/packages/generators/src/utils/modify-config-helper.ts +++ b/packages/generators/src/utils/modify-config-helper.ts @@ -39,7 +39,6 @@ export function modifyHelperUtil( configFile: string = DEFAULT_WEBPACK_CONFIG_FILENAME, packages?: string[], autoSetDefaults = false, - generateConfig = false, generationPath = '.', ): void { const configPath: string | null = null; @@ -135,7 +134,7 @@ export function modifyHelperUtil( ) as TransformConfig; // scaffold webpack config file from using .yo-rc.json - return runTransform(transformConfig, 'init', generateConfig, generationPath); + return runTransform(transformConfig, 'init', generationPath); } catch (error) { logger.error(error); process.exitCode = 2; diff --git a/packages/generators/src/utils/scaffold.ts b/packages/generators/src/utils/scaffold.ts index f7fed7cc34d..ec38c2278bd 100644 --- a/packages/generators/src/utils/scaffold.ts +++ b/packages/generators/src/utils/scaffold.ts @@ -39,13 +39,9 @@ function mapOptionsToTransform(config: Config): string[] { * and writes the file */ -export function runTransform(transformConfig: TransformConfig, action: string, generateConfig: boolean, generationPath: string): void { +export function runTransform(transformConfig: TransformConfig, action: string, generationPath: string): void { // webpackOptions.name sent to nameTransform if match const webpackConfig = Object.keys(transformConfig).filter((p: string): boolean => { - if (p == 'usingDefaults') { - return generateConfig; - } - return p !== 'configFile' && p !== 'configPath'; }); const initActionNotDefined = action && action !== 'init'; diff --git a/packages/init/README.md b/packages/init/README.md index fc6ea999a16..a1e392533cb 100644 --- a/packages/init/README.md +++ b/packages/init/README.md @@ -28,12 +28,6 @@ npx webpack-cli init npx webpack-cli init --auto ``` -**To force config generation** - -```bash -npx webpack-cli init --force -``` - **To scaffold in a specified path** ```bash diff --git a/packages/init/src/index.ts b/packages/init/src/index.ts index 077e673053c..e75210408ce 100644 --- a/packages/init/src/index.ts +++ b/packages/init/src/index.ts @@ -16,11 +16,6 @@ class InitCommand { type: Boolean, description: 'To generate default config', }, - { - name: 'force', - type: Boolean, - description: 'To force config generation', - }, { name: 'generation-path', type: String, @@ -34,7 +29,7 @@ class InitCommand { return; } - modifyHelperUtil(initGenerator, null, null, options.auto, options.force, options.generationPath); + modifyHelperUtil(initGenerator, null, null, options.auto, options.generationPath); }, ); } diff --git a/test/init/force/init-force.test.js b/test/init/force/init-force.test.js deleted file mode 100644 index bbcf9bdd36a..00000000000 --- a/test/init/force/init-force.test.js +++ /dev/null @@ -1,60 +0,0 @@ -'use strict'; - -const { green } = require('colorette'); -const fs = require('fs'); -const { join, resolve } = require('path'); -const rimraf = require('rimraf'); -const { runPromptWithAnswers } = require('../../utils/test-utils'); -const firstPrompt = 'Will your application have multiple bundles?'; - -const ENTER = '\x0D'; -const genPath = join(__dirname, 'test-assets'); - -const successLog = `You can now run ${green('yarn build')} to bundle your application!`; - -describe('init force flag', () => { - beforeAll(() => { - rimraf.sync(genPath); - fs.mkdirSync(genPath); - }); - - it('should scaffold webpack config', async () => { - const { stdout } = await runPromptWithAnswers( - genPath, - ['init', '--force'], - [`N${ENTER}`, ENTER, ENTER, ENTER, ENTER, ENTER, ENTER, ENTER], - ); - - expect(stdout).toBeTruthy(); - expect(stdout).toContain(firstPrompt); - - // Skip test in case installation fails - if (!fs.existsSync(resolve(genPath, './yarn.lock'))) { - return; - } - - // Test regressively files are scaffolded - const files = ['./package.json', './src/index.js', './webpack.config.js']; - - files.forEach((file) => { - expect(fs.existsSync(resolve(genPath, file))).toBeTruthy(); - }); - - const webpackConfig = require(join(genPath, 'webpack.config.js')); - - expect(webpackConfig.modules.rules).toEqual([]); - - // Check package json is correctly configured - const pkgJsonTests = () => { - const pkgJson = require(join(genPath, './package.json')); - expect(pkgJson).toBeTruthy(); - expect(pkgJson['devDependencies']).toBeTruthy(); - expect(pkgJson['devDependencies']['webpack']).toBeTruthy(); - expect(pkgJson['scripts']['build'] == 'webpack').toBeTruthy(); - }; - expect(pkgJsonTests).not.toThrow(); - - // Check we are not logging twice - expect(stdout.split(successLog).length - 1).toBe(1); - }); -}); From d004ded913b5048f88516047cdb941e6496c4982 Mon Sep 17 00:00:00 2001 From: James George Date: Mon, 1 Feb 2021 22:03:09 +0530 Subject: [PATCH 21/29] docs: remove references to non-existent packages (#2395) --- README.md | 1 - packages/README.md | 12 ++++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index bdf33ce0f0f..f0eed545f74 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,6 @@ Thus, webpack CLI provides different commands for many common tasks. The project also has several utility packages which are used by other commands -- [`utils`](./packages/utils/README.md) - Several utilities used across webpack-cli. - [`generators`](./packages/generators/README.md) - Contains all webpack-cli related yeoman generators. ## Getting started diff --git a/packages/README.md b/packages/README.md index 2791329cf10..ea522074275 100644 --- a/packages/README.md +++ b/packages/README.md @@ -13,12 +13,12 @@ This folder is the collection of those packages. ## Packages -1. [generators](https://github.com/webpack/webpack-cli/tree/master/packages/generators) -2. [info](https://github.com/webpack/webpack-cli/tree/master/packages/info) -3. [init](https://github.com/webpack/webpack-cli/tree/master/packages/init) -4. [migrate](https://www.npmjs.com/package/@webpack-cli/migrate) -5. [serve](https://github.com/webpack/webpack-cli/tree/master/packages/serve) -6. [utils](https://github.com/webpack/webpack-cli/tree/master/packages/utils) +1. [configtest](https://github.com/webpack/webpack-cli/tree/master/packages/configtest) +2. [generators](https://github.com/webpack/webpack-cli/tree/master/packages/generators) +3. [info](https://github.com/webpack/webpack-cli/tree/master/packages/info) +4. [init](https://github.com/webpack/webpack-cli/tree/master/packages/init) +5. [migrate](https://www.npmjs.com/package/@webpack-cli/migrate) +6. [serve](https://github.com/webpack/webpack-cli/tree/master/packages/serve) 7. [webpack-cli](https://github.com/webpack/webpack-cli/tree/master/packages/webpack-cli) ## Generic Installation From aebdbbc1f6e2761e7821cb3660bea686cce7b587 Mon Sep 17 00:00:00 2001 From: Alexander Akait <4567934+alexander-akait@users.noreply.github.com> Date: Mon, 1 Feb 2021 22:10:23 +0300 Subject: [PATCH 22/29] feat: support ES module configuration format (#2381) --- package.json | 4 ++- packages/webpack-cli/bin/cli.js | 9 +++-- packages/webpack-cli/lib/bootstrap.js | 4 ++- .../lib/utils/dynamic-import-loader.js | 13 +++++++ packages/webpack-cli/lib/utils/index.js | 4 +++ packages/webpack-cli/lib/webpack-cli.js | 35 +++++++++++------- test/config-format/coffee/coffee.test.js | 1 - test/config-format/coffee/package.json | 5 --- .../commonjs-default/commonjs-default.test.js | 11 ++++++ test/config-format/commonjs-default/main.js | 1 + .../commonjs-default/webpack.config.cjs | 12 +++++++ test/config-format/failure/failure.test.js | 16 ++++----- ...pack.config.coffee => webpack.config.iced} | 0 test/config-format/mjs/mjs.test.js | 13 +++---- test/config-format/typescript/package.json | 7 ---- .../typescript/typescript.test.js | 22 +++++------- .../typescript/webpack.config.ts | 2 +- .../custom-name/config.webpack.mjs | 10 ++++++ .../custom-name/custom-name.test.js | 19 ++++++++-- .../mjs-config/default-mjs-config.test.js | 11 +++--- test/config/error-mjs/config-error.test.js | 21 +++++++---- test/entry/scss/package.json | 10 +++--- test/watch/basic/basic.test.js | 8 ++--- test/watch/basic/src/index.js | 2 +- yarn.lock | 36 +++++++++++++++++-- 25 files changed, 191 insertions(+), 85 deletions(-) create mode 100644 packages/webpack-cli/lib/utils/dynamic-import-loader.js delete mode 100644 test/config-format/coffee/package.json create mode 100644 test/config-format/commonjs-default/commonjs-default.test.js create mode 100644 test/config-format/commonjs-default/main.js create mode 100644 test/config-format/commonjs-default/webpack.config.cjs rename test/config-format/failure/{webpack.config.coffee => webpack.config.iced} (100%) delete mode 100644 test/config-format/typescript/package.json create mode 100644 test/config-lookup/custom-name/config.webpack.mjs diff --git a/package.json b/package.json index a54dc077679..84f62d67bd3 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "pretest": "yarn build && yarn lint && yarn prepsuite", "test": "jest --reporters=default", "test:smoketests": "nyc node smoketests", - "test:coverage": "nyc jest --forceExit", + "test:coverage": "nyc --require ts-node/register jest --forceExit", "test:cli": "jest test --reporters=default --forceExit", "test:packages": "jest packages/ --reporters=default --forceExit", "test:ci": "yarn test:cli && yarn test:packages", @@ -64,6 +64,7 @@ "@typescript-eslint/eslint-plugin": "^2.34.0", "@typescript-eslint/parser": "^2.34.0", "@webpack-cli/migrate": "^1.1.2", + "coffeescript": "^2.5.1", "colorette": "^1.2.1", "commitlint": "^11.0.0", "commitlint-config-cz": "^0.13.2", @@ -88,6 +89,7 @@ "rimraf": "^3.0.2", "strip-ansi": "^6.0.0", "ts-jest": "^26.4.3", + "ts-node": "^9.1.1", "typescript": "^4.1.3", "webpack": "^5.18.0", "webpack-bundle-analyzer": "^4.3.0", diff --git a/packages/webpack-cli/bin/cli.js b/packages/webpack-cli/bin/cli.js index c78e0935e9f..db74156aa8b 100755 --- a/packages/webpack-cli/bin/cli.js +++ b/packages/webpack-cli/bin/cli.js @@ -1,6 +1,11 @@ #!/usr/bin/env node 'use strict'; + +const Module = require('module'); + +const originalModuleCompile = Module.prototype._compile; + require('v8-compile-cache'); const importLocal = require('import-local'); @@ -15,7 +20,7 @@ if (importLocal(__filename)) { process.title = 'webpack'; if (utils.packageExists('webpack')) { - runCLI(process.argv); + runCLI(process.argv, originalModuleCompile); } else { const { promptInstallation, logger, colors } = utils; @@ -25,7 +30,7 @@ if (utils.packageExists('webpack')) { .then(() => { logger.success(`${colors.bold('webpack')} was installed successfully.`); - runCLI(process.argv); + runCLI(process.argv, originalModuleCompile); }) .catch(() => { logger.error(`Action Interrupted, Please try once again or install ${colors.bold('webpack')} manually.`); diff --git a/packages/webpack-cli/lib/bootstrap.js b/packages/webpack-cli/lib/bootstrap.js index c01ca2b7ce7..0a83a81c9e2 100644 --- a/packages/webpack-cli/lib/bootstrap.js +++ b/packages/webpack-cli/lib/bootstrap.js @@ -1,11 +1,13 @@ const WebpackCLI = require('./webpack-cli'); const utils = require('./utils'); -const runCLI = async (args) => { +const runCLI = async (args, originalModuleCompile) => { try { // Create a new instance of the CLI object const cli = new WebpackCLI(); + cli._originalModuleCompile = originalModuleCompile; + await cli.run(args); } catch (error) { utils.logger.error(error); diff --git a/packages/webpack-cli/lib/utils/dynamic-import-loader.js b/packages/webpack-cli/lib/utils/dynamic-import-loader.js new file mode 100644 index 00000000000..a9dbedc197b --- /dev/null +++ b/packages/webpack-cli/lib/utils/dynamic-import-loader.js @@ -0,0 +1,13 @@ +function dynamicImportLoader() { + let importESM; + + try { + importESM = new Function('id', 'return import(id);'); + } catch (e) { + importESM = null; + } + + return importESM; +} + +module.exports = dynamicImportLoader; diff --git a/packages/webpack-cli/lib/utils/index.js b/packages/webpack-cli/lib/utils/index.js index 223e9c0cf3f..045c98f2aab 100644 --- a/packages/webpack-cli/lib/utils/index.js +++ b/packages/webpack-cli/lib/utils/index.js @@ -19,6 +19,10 @@ module.exports = { return require('./capitalize-first-letter'); }, + get dynamicImportLoader() { + return require('./dynamic-import-loader'); + }, + get getPackageManager() { return require('./get-package-manager'); }, diff --git a/packages/webpack-cli/lib/webpack-cli.js b/packages/webpack-cli/lib/webpack-cli.js index 04d28a9135e..79f7070534c 100644 --- a/packages/webpack-cli/lib/webpack-cli.js +++ b/packages/webpack-cli/lib/webpack-cli.js @@ -1,5 +1,7 @@ const fs = require('fs'); const path = require('path'); +const { pathToFileURL } = require('url'); +const Module = require('module'); const { program } = require('commander'); const utils = require('./utils'); @@ -1137,26 +1139,35 @@ class WebpackCLI { } } - const { pathToFileURL } = require('url'); - - let importESM; - - try { - importESM = new Function('id', 'return import(id);'); - } catch (e) { - importESM = null; - } - let options; try { try { options = require(configPath); } catch (error) { - if (pathToFileURL && importESM && error.code === 'ERR_REQUIRE_ESM') { + let previousModuleCompile; + + // TODO Workaround https://github.com/zertosh/v8-compile-cache/issues/30 + if (this._originalModuleCompile) { + previousModuleCompile = Module.prototype._compile; + + Module.prototype._compile = this._originalModuleCompile; + } + + const dynamicImportLoader = this.utils.dynamicImportLoader(); + + if (this._originalModuleCompile) { + Module.prototype._compile = previousModuleCompile; + } + + if ( + (error.code === 'ERR_REQUIRE_ESM' || process.env.WEBPACK_CLI_FORCE_LOAD_ESM_CONFIG) && + pathToFileURL && + dynamicImportLoader + ) { const urlForConfig = pathToFileURL(configPath); - options = await importESM(urlForConfig); + options = await dynamicImportLoader(urlForConfig); options = options.default; return { options, path: configPath }; diff --git a/test/config-format/coffee/coffee.test.js b/test/config-format/coffee/coffee.test.js index 84f6ada8f75..1a31dbd4849 100644 --- a/test/config-format/coffee/coffee.test.js +++ b/test/config-format/coffee/coffee.test.js @@ -1,4 +1,3 @@ -// eslint-disable-next-line node/no-unpublished-require const { run } = require('../../utils/test-utils'); describe('webpack cli', () => { diff --git a/test/config-format/coffee/package.json b/test/config-format/coffee/package.json deleted file mode 100644 index 79463144cb1..00000000000 --- a/test/config-format/coffee/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "dependencies": { - "coffeescript": "^2.5.1" - } -} diff --git a/test/config-format/commonjs-default/commonjs-default.test.js b/test/config-format/commonjs-default/commonjs-default.test.js new file mode 100644 index 00000000000..b31d62a3655 --- /dev/null +++ b/test/config-format/commonjs-default/commonjs-default.test.js @@ -0,0 +1,11 @@ +const { run } = require('../../utils/test-utils'); + +describe('webpack cli', () => { + it('should support CommonJS file', () => { + const { exitCode, stderr, stdout } = run(__dirname, ['-c', 'webpack.config.cjs'], false); + + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toBeTruthy(); + }); +}); diff --git a/test/config-format/commonjs-default/main.js b/test/config-format/commonjs-default/main.js new file mode 100644 index 00000000000..8ed93e41fb2 --- /dev/null +++ b/test/config-format/commonjs-default/main.js @@ -0,0 +1 @@ +console.log('Hoshiumi'); diff --git a/test/config-format/commonjs-default/webpack.config.cjs b/test/config-format/commonjs-default/webpack.config.cjs new file mode 100644 index 00000000000..415d965a247 --- /dev/null +++ b/test/config-format/commonjs-default/webpack.config.cjs @@ -0,0 +1,12 @@ +const path = require('path'); + +const config = { + mode: 'production', + entry: './main.js', + output: { + path: path.resolve(__dirname, 'dist'), + filename: 'foo.bundle.js', + }, +}; + +module.exports.default = config; diff --git a/test/config-format/failure/failure.test.js b/test/config-format/failure/failure.test.js index 125c94e31bf..0befcb891ca 100644 --- a/test/config-format/failure/failure.test.js +++ b/test/config-format/failure/failure.test.js @@ -2,17 +2,15 @@ const path = require('path'); const { run } = require('../../utils/test-utils'); -describe('webpack cli', () => { - it('should support mjs config format', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['-c', 'webpack.config.coffee']); +describe('failure', () => { + it('should log error on not installed registers', () => { + const { exitCode, stderr, stdout } = run(__dirname, ['-c', 'webpack.config.iced']); expect(exitCode).toBe(2); - expect(stderr).toContain(`Unable load '${path.resolve(__dirname, './webpack.config.coffee')}'`); - expect(stderr).toContain('Unable to use specified module loaders for ".coffee".'); - expect(stderr).toContain("Cannot find module 'coffeescript/register'"); - expect(stderr).toContain("Cannot find module 'coffee-script/register'"); - expect(stderr).toContain("Cannot find module 'coffeescript'"); - expect(stderr).toContain("Cannot find module 'coffee-script'"); + expect(stderr).toContain(`Unable load '${path.resolve(__dirname, './webpack.config.iced')}'`); + expect(stderr).toContain('Unable to use specified module loaders for ".iced".'); + expect(stderr).toContain("Cannot find module 'iced-coffee-script/register'"); + expect(stderr).toContain("Cannot find module 'iced-coffee-script'"); expect(stderr).toContain('Please install one of them'); expect(stdout).toBeFalsy(); }); diff --git a/test/config-format/failure/webpack.config.coffee b/test/config-format/failure/webpack.config.iced similarity index 100% rename from test/config-format/failure/webpack.config.coffee rename to test/config-format/failure/webpack.config.iced diff --git a/test/config-format/mjs/mjs.test.js b/test/config-format/mjs/mjs.test.js index e8ada298f2a..97853c18bfd 100644 --- a/test/config-format/mjs/mjs.test.js +++ b/test/config-format/mjs/mjs.test.js @@ -2,16 +2,17 @@ const { run } = require('../../utils/test-utils'); describe('webpack cli', () => { it('should support mjs config format', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['-c', 'webpack.config.mjs'], [], { DISABLE_V8_COMPILE_CACHE: true }); + const { exitCode, stderr, stdout } = run(__dirname, ['-c', 'webpack.config.mjs'], { + env: { WEBPACK_CLI_FORCE_LOAD_ESM_CONFIG: true }, + }); - if (exitCode === 0) { + if (/Error: Not supported/.test(stderr)) { + expect(exitCode).toBe(2); + expect(stdout).toBeFalsy(); + } else { expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); expect(stdout).toBeTruthy(); - } else { - expect(exitCode).toBe(2); - expect(/Cannot use import statement outside a module/.test(stderr) || /Unexpected token/.test(stderr)).toBe(true); - expect(stdout).toBeFalsy(); } }); }); diff --git a/test/config-format/typescript/package.json b/test/config-format/typescript/package.json deleted file mode 100644 index 43237a25bed..00000000000 --- a/test/config-format/typescript/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "dependencies": { - "typescript": "^3.8.2", - "ts-node": "^8.6.2", - "tsconfig-paths": "^3.9.0" - } -} diff --git a/test/config-format/typescript/typescript.test.js b/test/config-format/typescript/typescript.test.js index 21fadb957e7..b511e69843e 100644 --- a/test/config-format/typescript/typescript.test.js +++ b/test/config-format/typescript/typescript.test.js @@ -1,20 +1,14 @@ -/* eslint-disable node/no-unpublished-require */ -const { run, runInstall } = require('../../utils/test-utils'); +const { run } = require('../../utils/test-utils'); const { existsSync } = require('fs'); const { resolve } = require('path'); describe('webpack cli', () => { - it.skip( - 'should support typescript file', - async () => { - await runInstall(__dirname); - const { exitCode, stderr, stdout } = run(__dirname, ['-c', './webpack.config.ts']); + it('should support typescript file', () => { + const { exitCode, stderr, stdout } = run(__dirname, ['-c', './webpack.config.ts']); - expect(stderr).toBeFalsy(); - expect(stdout).toBeTruthy(); - expect(exitCode).toBe(0); - expect(existsSync(resolve(__dirname, 'bin/foo.bundle.js'))).toBeTruthy(); - }, - 1000 * 60 * 5, - ); + expect(stderr).toBeFalsy(); + expect(stdout).toBeTruthy(); + expect(exitCode).toBe(0); + expect(existsSync(resolve(__dirname, 'dist/foo.bundle.js'))).toBeTruthy(); + }); }); diff --git a/test/config-format/typescript/webpack.config.ts b/test/config-format/typescript/webpack.config.ts index 4a17fa148c6..bbc70963b3b 100644 --- a/test/config-format/typescript/webpack.config.ts +++ b/test/config-format/typescript/webpack.config.ts @@ -11,4 +11,4 @@ const config = { }, }; -export default config; +export = config; diff --git a/test/config-lookup/custom-name/config.webpack.mjs b/test/config-lookup/custom-name/config.webpack.mjs new file mode 100644 index 00000000000..272b905bc1c --- /dev/null +++ b/test/config-lookup/custom-name/config.webpack.mjs @@ -0,0 +1,10 @@ +import { fileURLToPath } from 'url'; +import path from 'path'; + +export default { + entry: './a.js', + output: { + path: path.resolve(path.dirname(fileURLToPath(import.meta.url)), 'dist'), + filename: 'a.bundle.js', + }, +}; diff --git a/test/config-lookup/custom-name/custom-name.test.js b/test/config-lookup/custom-name/custom-name.test.js index aa9bcd1c439..1f088a363e4 100644 --- a/test/config-lookup/custom-name/custom-name.test.js +++ b/test/config-lookup/custom-name/custom-name.test.js @@ -4,11 +4,26 @@ const { resolve } = require('path'); const { run } = require('../../utils/test-utils'); describe('custom config file', () => { - it('should work', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['--config', resolve(__dirname, 'config.webpack.js')], false); + it('should work with cjs format', () => { + const { exitCode, stderr, stdout } = run(__dirname, ['--config', resolve(__dirname, 'config.webpack.js')]); expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); expect(stdout).toBeTruthy(); }); + + it('should work with esm format', () => { + const { exitCode, stderr, stdout } = run(__dirname, ['--config', resolve(__dirname, 'config.webpack.mjs')], { + env: { WEBPACK_CLI_FORCE_LOAD_ESM_CONFIG: true }, + }); + + if (/Error: Not supported/.test(stderr)) { + expect(exitCode).toBe(2); + expect(stdout).toBeFalsy(); + } else { + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toBeTruthy(); + } + }); }); diff --git a/test/config/defaults/mjs-config/default-mjs-config.test.js b/test/config/defaults/mjs-config/default-mjs-config.test.js index b2fe3551bdc..f5b443c9613 100644 --- a/test/config/defaults/mjs-config/default-mjs-config.test.js +++ b/test/config/defaults/mjs-config/default-mjs-config.test.js @@ -4,9 +4,12 @@ const { run, isWebpack5 } = require('../../../utils/test-utils'); describe('Default Config:', () => { it('Should be able to pick mjs config by default', () => { - const { exitCode, stderr, stdout } = run(__dirname, [], [], { DISABLE_V8_COMPILE_CACHE: true }); + const { exitCode, stderr, stdout } = run(__dirname, [], { env: { WEBPACK_CLI_FORCE_LOAD_ESM_CONFIG: true } }); - if (exitCode === 0) { + if (/Error: Not supported/.test(stderr)) { + expect(exitCode).toEqual(2); + expect(stdout).toBeFalsy(); + } else { expect(exitCode).toEqual(0); expect(stderr).toBeFalsy(); // default entry should be used @@ -23,10 +26,6 @@ describe('Default Config:', () => { // check that the output file exists expect(fs.existsSync(path.join(__dirname, '/dist/test-output.js'))).toBeTruthy(); - } else { - expect(exitCode).toEqual(2); - expect(stderr).toContain('Unexpected token'); - expect(stdout).toBeFalsy(); } }); }); diff --git a/test/config/error-mjs/config-error.test.js b/test/config/error-mjs/config-error.test.js index 4abbe2e5b48..eb90cbf1e76 100644 --- a/test/config/error-mjs/config-error.test.js +++ b/test/config/error-mjs/config-error.test.js @@ -4,22 +4,31 @@ const { run } = require('../../utils/test-utils'); describe('config error', () => { it('should throw error with invalid configuration', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['-c', resolve(__dirname, 'webpack.config.mjs')], [], { - DISABLE_V8_COMPILE_CACHE: true, + const { exitCode, stderr, stdout } = run(__dirname, ['-c', resolve(__dirname, 'webpack.config.mjs')], { + env: { WEBPACK_CLI_FORCE_LOAD_ESM_CONFIG: true }, }); expect(exitCode).toBe(2); - expect(/Invalid configuration object/.test(stderr) || /Unexpected token/.test(stderr)).toBe(true); + + if (!/Error: Not supported/.test(stderr)) { + expect(stderr).toContain('Invalid configuration object'); + expect(stderr).toContain(`"development" | "production" | "none"`); + } + expect(stdout).toBeFalsy(); }); it('should throw syntax error and exit with non-zero exit code', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['-c', resolve(__dirname, 'syntax-error.mjs')], [], { - DISABLE_V8_COMPILE_CACHE: true, + const { exitCode, stderr, stdout } = run(__dirname, ['-c', resolve(__dirname, 'syntax-error.mjs')], { + env: { WEBPACK_CLI_FORCE_LOAD_ESM_CONFIG: true }, }); expect(exitCode).toBe(2); - expect(stderr).toContain('SyntaxError: Unexpected token'); + + if (!/Error: Not supported/.test(stderr)) { + expect(stderr).toContain('SyntaxError: Unexpected token'); + } + expect(stdout).toBeFalsy(); }); }); diff --git a/test/entry/scss/package.json b/test/entry/scss/package.json index 2ddfa5b1c12..11b90db6ca3 100644 --- a/test/entry/scss/package.json +++ b/test/entry/scss/package.json @@ -1,9 +1,9 @@ { "dependencies": { - "css-loader": "^3.4.2", - "style-loader": "^1.1.3", - "sass-loader": "^8.0.2", - "mini-css-extract-plugin": "^0.9.0", - "node-sass": "^4.13.1" + "css-loader": "^5.0.1", + "style-loader": "^2.0.0", + "sass-loader": "^10.1.1", + "mini-css-extract-plugin": "^1.3.5", + "node-sass": "^5.0.0" } } diff --git a/test/watch/basic/basic.test.js b/test/watch/basic/basic.test.js index 771e4f81344..29013daeff3 100644 --- a/test/watch/basic/basic.test.js +++ b/test/watch/basic/basic.test.js @@ -38,7 +38,7 @@ describe('basic', () => { if (!modified) { process.nextTick(() => { - writeFileSync(resolve(__dirname, './src/index.js'), `console.log('watch flag test');`); + writeFileSync(resolve(__dirname, './src/index.js'), `console.log('watch flag test');\n`); }); modified = true; @@ -71,7 +71,7 @@ describe('basic', () => { if (!modified) { process.nextTick(() => { - writeFileSync(resolve(__dirname, './src/index.js'), `console.log('watch flag test');`); + writeFileSync(resolve(__dirname, './src/index.js'), `console.log('watch flag test');\n`); }); modified = true; @@ -106,7 +106,7 @@ describe('basic', () => { if (!modified) { process.nextTick(() => { - writeFileSync(resolve(__dirname, './src/entry.js'), `console.log('watch flag test');`); + writeFileSync(resolve(__dirname, './src/entry.js'), `console.log('watch flag test');\n`); }); modified = true; @@ -139,7 +139,7 @@ describe('basic', () => { if (!modified) { process.nextTick(() => { - writeFileSync(resolve(__dirname, './src/index.js'), `console.log('watch flag test');`); + writeFileSync(resolve(__dirname, './src/index.js'), `console.log('watch flag test');\n`); }); modified = true; diff --git a/test/watch/basic/src/index.js b/test/watch/basic/src/index.js index efc51ca0a97..1d8734ee1c8 100644 --- a/test/watch/basic/src/index.js +++ b/test/watch/basic/src/index.js @@ -1 +1 @@ -console.log('watch flag test'); \ No newline at end of file +console.log('watch flag test'); diff --git a/yarn.lock b/yarn.lock index 2d97813f88f..7cab2c49a97 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2495,6 +2495,11 @@ are-we-there-yet@~1.1.2: delegates "^1.0.0" readable-stream "^2.0.6" +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -3307,6 +3312,11 @@ code-point-at@^1.0.0: resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= +coffeescript@^2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/coffeescript/-/coffeescript-2.5.1.tgz#b2442a1f2c806139669534a54adc35010559d16a" + integrity sha512-J2jRPX0eeFh5VKyVnoLrfVFgLZtnnmp96WQSLAS8OrLm2wtQLcnikYKe1gViJKDH7vucjuhHvBKKBP3rKcD1tQ== + collect-v8-coverage@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" @@ -3657,6 +3667,11 @@ create-error-class@^3.0.0: dependencies: capture-stack-trace "^1.0.0" +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" @@ -7436,7 +7451,7 @@ make-dir@^3.0.0, make-dir@^3.0.2: dependencies: semver "^6.0.0" -make-error@1.x: +make-error@1.x, make-error@^1.1.1: version "1.3.6" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== @@ -9889,7 +9904,7 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@^0.5.16, source-map-support@^0.5.6, source-map-support@~0.5.19: +source-map-support@^0.5.16, source-map-support@^0.5.17, source-map-support@^0.5.6, source-map-support@~0.5.19: version "0.5.19" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== @@ -10593,6 +10608,18 @@ ts-jest@^26.4.3: semver "7.x" yargs-parser "20.x" +ts-node@^9.1.1: + version "9.1.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.1.1.tgz#51a9a450a3e959401bda5f004a72d54b936d376d" + integrity sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg== + dependencies: + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + source-map-support "^0.5.17" + yn "3.1.1" + tslib@^1.8.1, tslib@^1.9.0: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" @@ -11490,6 +11517,11 @@ yeoman-test@^2.7.0: yeoman-environment "^2.10.0" yeoman-generator "^4.10.0" +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" From 9967de91c34cf36783ba7d622be06bc4ae4661f6 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 1 Feb 2021 22:10:57 +0300 Subject: [PATCH 23/29] chore(deps): bump envinfo from 7.7.3 to 7.7.4 (#2396) Bumps [envinfo](https://github.com/tabrindle/envinfo) from 7.7.3 to 7.7.4. - [Release notes](https://github.com/tabrindle/envinfo/releases) - [Commits](https://github.com/tabrindle/envinfo/compare/7.7.3...7.7.4) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 7cab2c49a97..1eee835e480 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4232,9 +4232,9 @@ env-paths@^2.2.0: integrity sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA== envinfo@^7.3.1, envinfo@^7.7.3: - version "7.7.3" - resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.7.3.tgz#4b2d8622e3e7366afb8091b23ed95569ea0208cc" - integrity sha512-46+j5QxbPWza0PB1i15nZx0xQ4I/EfQxg9J8Had3b408SV63nEtor2e+oiY63amTo9KTuh2a3XLObNwduxYwwA== + version "7.7.4" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.7.4.tgz#c6311cdd38a0e86808c1c9343f667e4267c4a320" + integrity sha512-TQXTYFVVwwluWSFis6K2XKxgrD22jEv0FTuLCQI+OjH7rn93+iY0fSSFM5lrSxFY+H1+B0/cvvlamr3UsBivdQ== err-code@^1.0.0: version "1.1.2" From 805f9ffb3493f7bea2d1be2c6e3c8884abebe621 Mon Sep 17 00:00:00 2001 From: Anshuman Verma Date: Tue, 2 Feb 2021 16:27:14 +0530 Subject: [PATCH 24/29] chore: use conventional commitlint (#2394) --- .cz-config.js | 32 ----------------------------- commitlint.config.js | 20 +----------------- package.json | 11 +--------- yarn.lock | 48 +++++++++++++------------------------------- 4 files changed, 16 insertions(+), 95 deletions(-) delete mode 100644 .cz-config.js diff --git a/.cz-config.js b/.cz-config.js deleted file mode 100644 index 11703d0b2a1..00000000000 --- a/.cz-config.js +++ /dev/null @@ -1,32 +0,0 @@ -/** - * @license Copyright 2017 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by - * applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS - * OF ANY KIND, either express or implied. See the License for the specific - * language governing permissions and limitations under the License. - */ -// Based on https://github.com/GoogleChrome/lighthouse/blob/master/.cz-config.js - -'use strict'; - -module.exports = { - allowBreakingChanges: ['ast'], - allowCustomScopes: true, - scopes: [], - // sort type values in asc - types: [ - { value: 'ast', name: 'ast: init, add, etc' }, - { value: 'break', name: 'break: Changes that break the behaviour of the cli' }, - { value: 'chore', name: 'chore: Updating deps, docs, linting, etc' }, - { value: 'cli', name: 'cli: Core CLI things' }, - { value: 'docs', name: 'docs: Documentation' }, - { value: 'feat', name: 'feat: A new feature' }, - { value: 'fix', name: 'fix: Bugs, typos, etc' }, - { value: 'misc', name: 'misc: Other formats like tweaks and such' }, - { value: 'tests', name: 'tests: Tests, jest, etc' }, - { value: 'refactor', name: 'refactor: A code change that neither fixes a bug nor adds a feature' }, - ], -}; diff --git a/commitlint.config.js b/commitlint.config.js index d816fd4e9fc..2f9d1aa0e6c 100644 --- a/commitlint.config.js +++ b/commitlint.config.js @@ -1,21 +1,3 @@ -'use strict'; - module.exports = { - extends: ['cz', '@commitlint/config-lerna-scopes'], - rules: { - 'body-leading-blank': [1, 'always'], - 'footer-leading-blank': [1, 'always'], - 'header-max-length': [2, 'always', 80], - 'scope-case': [2, 'always', 'lowerCase'], - 'scope-empty': [0, 'never'], - 'subject-case': [2, 'never', ['sentence-case', 'start-case', 'pascal-case', 'upper-case']], - 'subject-empty': [0, 'never'], - 'subject-full-stop': [2, 'never', '.'], - 'type-case': [2, 'always', 'lowerCase'], - // turn it on once CLI will be inside its own package, so the scope will be the name of the packaged - // part of the @commitlint/config-lerna-scopes - 'scope-enum': [0, 'never'], - 'type-empty': [2, 'never'], - 'type-enum': [2, 'always', ['ast', 'break', 'chore', 'cli', 'docs', 'feat', 'fix', 'misc', 'tests', 'refactor']], - }, + extends: ['@commitlint/config-conventional'], }; diff --git a/package.json b/package.json index 84f62d67bd3..6114c3636e1 100644 --- a/package.json +++ b/package.json @@ -45,20 +45,12 @@ "publish:monorepo": "yarn build && lerna version && lerna publish from-git", "update:docs": "node ./scripts/updateDocs" }, - "config": { - "commitizen": { - "path": "./node_modules/cz-customizable" - }, - "cz-customizable": { - "config": "./.cz-config.js" - } - }, "peerDependencies": { "webpack": "4.x.x || 5.x.x" }, "devDependencies": { "@commitlint/cli": "^11.0.0", - "@commitlint/config-lerna-scopes": "^11.0.0", + "@commitlint/config-conventional": "^11.0.0", "@types/jest": "^26.0.15", "@types/node": "^14.14.6", "@typescript-eslint/eslint-plugin": "^2.34.0", @@ -67,7 +59,6 @@ "coffeescript": "^2.5.1", "colorette": "^1.2.1", "commitlint": "^11.0.0", - "commitlint-config-cz": "^0.13.2", "concat-stream": "^2.0.0", "cz-customizable": "^6.3.0", "del-cli": "^3.0.1", diff --git a/yarn.lock b/yarn.lock index 1eee835e480..094afc705ea 100644 --- a/yarn.lock +++ b/yarn.lock @@ -419,14 +419,12 @@ resolve-global "1.0.0" yargs "^15.1.0" -"@commitlint/config-lerna-scopes@^11.0.0": +"@commitlint/config-conventional@^11.0.0": version "11.0.0" - resolved "https://registry.yarnpkg.com/@commitlint/config-lerna-scopes/-/config-lerna-scopes-11.0.0.tgz#4152287c5d13ea844160507523b2f98b015adf4a" - integrity sha512-/PjLKefMlnG+Sk27MY3MZo+T/9/PrgDcLk1YCSPVHNkXibXiS2Hb5NEMuNHzPxwts4IvJo0WIOb0YOBx5GBsdA== + resolved "https://registry.yarnpkg.com/@commitlint/config-conventional/-/config-conventional-11.0.0.tgz#3fa300a1b639273946de3c3f15e1cda518333422" + integrity sha512-SNDRsb5gLuDd2PL83yCOQX6pE7gevC79UPFx+GLbLfw6jGnnbO9/tlL76MLD8MOViqGbo7ZicjChO9Gn+7tHhA== dependencies: - import-from "3.0.0" - resolve-pkg "2.0.0" - semver "7.3.2" + conventional-changelog-conventionalcommits "^4.3.1" "@commitlint/ensure@^11.0.0": version "11.0.0" @@ -2460,11 +2458,6 @@ anymatch@^3.0.3: normalize-path "^3.0.0" picomatch "^2.0.4" -app-root-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-3.0.0.tgz#210b6f43873227e18a4b810a032283311555d5ad" - integrity sha512-qMcx+Gy2UZynHjOHOIXPNvpf+9cjvk3cWrBBK7zg4gH9+clobJRb9NGzcT7mQTcV/6Gm/1WelUtqxVXnNlrwcw== - append-transform@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-2.0.0.tgz#99d9d29c7b38391e6f428d28ce136551f0b77e12" @@ -3399,14 +3392,6 @@ commander@^7.0.0: resolved "https://registry.yarnpkg.com/commander/-/commander-7.0.0.tgz#3e2bbfd8bb6724760980988fb5b22b7ee6b71ab2" integrity sha512-ovx/7NkTrnPuIV8sqk/GjUIIM1+iUQeqA3ye2VNpq9sVoiZsooObWlQy+OPWGI17GDaEoybuAGJm6U8yC077BA== -commitlint-config-cz@^0.13.2: - version "0.13.2" - resolved "https://registry.yarnpkg.com/commitlint-config-cz/-/commitlint-config-cz-0.13.2.tgz#83f98a1217fb9e1e7cedd6d1d4fdb2d1492a867e" - integrity sha512-2oN0pXWwDtoKaWW35Haa3xUqWU7761OqM5yu5/UqmklBiznl9WDwoEJ5JIGzHE6qzTmBjAvITToyGNVUcjT/dg== - dependencies: - app-root-path "~3.0.0" - lodash.clonedeep "~4.5.0" - commitlint@^11.0.0: version "11.0.0" resolved "https://registry.yarnpkg.com/commitlint/-/commitlint-11.0.0.tgz#a60f759b938c97c5d601c881cfe71b1d4051d219" @@ -3520,6 +3505,15 @@ conventional-changelog-angular@^5.0.0, conventional-changelog-angular@^5.0.3: compare-func "^2.0.0" q "^1.5.1" +conventional-changelog-conventionalcommits@^4.3.1: + version "4.5.0" + resolved "https://registry.yarnpkg.com/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.5.0.tgz#a02e0b06d11d342fdc0f00c91d78265ed0bc0a62" + integrity sha512-buge9xDvjjOxJlyxUnar/+6i/aVEVGA7EEh4OafBCXPlLUQPGbRUBhBUveWRxzvR8TEjhKEP4BdepnpG2FSZXw== + dependencies: + compare-func "^2.0.0" + lodash "^4.17.15" + q "^1.5.1" + conventional-changelog-core@^3.1.6: version "3.2.3" resolved "https://registry.yarnpkg.com/conventional-changelog-core/-/conventional-changelog-core-3.2.3.tgz#b31410856f431c847086a7dcb4d2ca184a7d88fb" @@ -5841,13 +5835,6 @@ import-fresh@^3.0.0, import-fresh@^3.2.1: parent-module "^1.0.0" resolve-from "^4.0.0" -import-from@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/import-from/-/import-from-3.0.0.tgz#055cfec38cd5a27d8057ca51376d7d3bf0891966" - integrity sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ== - dependencies: - resolve-from "^5.0.0" - import-local@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" @@ -7292,7 +7279,7 @@ lodash._reinterpolate@^3.0.0: resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= -lodash.clonedeep@^4.5.0, lodash.clonedeep@~4.5.0: +lodash.clonedeep@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= @@ -9384,13 +9371,6 @@ resolve-global@1.0.0, resolve-global@^1.0.0: dependencies: global-dirs "^0.1.1" -resolve-pkg@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/resolve-pkg/-/resolve-pkg-2.0.0.tgz#ac06991418a7623edc119084edc98b0e6bf05a41" - integrity sha512-+1lzwXehGCXSeryaISr6WujZzowloigEofRB+dj75y9RRa/obVcYgbHJd53tdYw8pvZj8GojXaaENws8Ktw/hQ== - dependencies: - resolve-from "^5.0.0" - resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" From ad1a6b83dfa83737f561180384a7968d90472e70 Mon Sep 17 00:00:00 2001 From: Alexander Akait <4567934+alexander-akait@users.noreply.github.com> Date: Tue, 2 Feb 2021 15:28:21 +0300 Subject: [PATCH 25/29] docs: update (#2398) --- .github/CONTRIBUTING.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index d7d77e2a22d..c394cda8e83 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -211,16 +211,17 @@ format that includes a **type** and a **subject**: This is the list of _type_ of commits that we accept: -- **ast** : Init, migrate, etc. -- **break** : Changes that break the behaviour of the cli. +- **build** : Changes that affect the build system or external dependencies (example scopes: typescript, webpack, npm). - **chore** : Updating deps, docs, linting, etc. -- **cli** : Changes related to core CLI things. +- **ci** : Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs) - **docs** : Documentation only changes. - **feat** : A new feature. -- **fix** : A bug fix, typos, etc. -- **misc** : Other formats like tweaks and such. -- **tests** : Adding missing or correcting existing tests. +- **fix** : A bug fix. +- **perf** : A code change that improves performance. - **refactor** : A code change that neither fixes a bug nor adds a feature. +- **revert** : Reverts the previous commit. +- **style** : Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc). +- **test** : Adding missing tests or correcting existing tests. The **header** is mandatory. From b50d71b0bb6ad679a00b06a9dab6ceb49ed99c33 Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Tue, 2 Feb 2021 19:23:59 +0530 Subject: [PATCH 26/29] test: improve tests for --merge (#2399) --- test/merge/config/1.js | 8 ++++++-- test/merge/config/2.js | 5 +++-- test/merge/config/3.js | 6 ++++++ test/merge/config/first-entry.js | 1 + test/merge/config/merge-config.test.js | 22 +++++++++++++++++++--- test/merge/config/second-entry.js | 1 + test/merge/config/some_entry.js | 1 - test/merge/config/third-entry.js | 1 + 8 files changed, 37 insertions(+), 8 deletions(-) create mode 100644 test/merge/config/3.js create mode 100644 test/merge/config/first-entry.js create mode 100644 test/merge/config/second-entry.js delete mode 100644 test/merge/config/some_entry.js create mode 100644 test/merge/config/third-entry.js diff --git a/test/merge/config/1.js b/test/merge/config/1.js index 5051ea4b9d9..b09ad20ba61 100644 --- a/test/merge/config/1.js +++ b/test/merge/config/1.js @@ -1,6 +1,10 @@ +const WebpackCLITestPlugin = require('../../utils/webpack-cli-test-plugin'); + module.exports = { - entry: './old_entry.js', + entry: './first-entry.js', + mode: 'development', output: { - filename: 'badfile.js', + filename: 'first-output.js', }, + plugins: [new WebpackCLITestPlugin()], }; diff --git a/test/merge/config/2.js b/test/merge/config/2.js index 2c99fa4d4b7..cdf6f428467 100644 --- a/test/merge/config/2.js +++ b/test/merge/config/2.js @@ -1,6 +1,7 @@ module.exports = { - entry: './some_entry.js', + entry: './second-entry.js', + target: 'node', output: { - filename: 'merged.js', + filename: 'second-output.js', }, }; diff --git a/test/merge/config/3.js b/test/merge/config/3.js new file mode 100644 index 00000000000..eb2a7d3a6f5 --- /dev/null +++ b/test/merge/config/3.js @@ -0,0 +1,6 @@ +module.exports = { + entry: './third-entry.js', + output: { + filename: 'third-output.js', + }, +}; diff --git a/test/merge/config/first-entry.js b/test/merge/config/first-entry.js new file mode 100644 index 00000000000..e5ba023838e --- /dev/null +++ b/test/merge/config/first-entry.js @@ -0,0 +1 @@ +console.log('first'); diff --git a/test/merge/config/merge-config.test.js b/test/merge/config/merge-config.test.js index 916eb44c750..8ac300abb4c 100644 --- a/test/merge/config/merge-config.test.js +++ b/test/merge/config/merge-config.test.js @@ -8,7 +8,22 @@ describe('merge flag configuration', () => { expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); - expect(stdout).toContain('option has not been set, webpack will fallback to'); + expect(stdout).toContain('WebpackCLITestPlugin'); // from 1.js + expect(stdout).toContain('second-output.js'); // from 2.js + }); + + it('merges more than two configurations together', () => { + const { exitCode, stderr, stdout } = run( + __dirname, + ['--config', './1.js', '--config', './2.js', '--config', './3.js', '--merge'], + false, + ); + + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toContain('WebpackCLITestPlugin'); // from 1.js + expect(stdout).toContain("target: 'node'"); // from 2.js + expect(stdout).toContain('third-output.js'); // from 3.js }); it('merges two configurations together with flag alias', () => { @@ -16,11 +31,12 @@ describe('merge flag configuration', () => { expect(exitCode).toBe(0); expect(stderr).toBeFalsy(); - expect(stdout).toContain('merged.js'); + expect(stdout).toContain('WebpackCLITestPlugin'); // from 1.js + expect(stdout).toContain('second-output.js'); // from 2.js }); it('fails when there are less than 2 configurations to merge', () => { - const { exitCode, stderr, stdout } = run(__dirname, ['--config', './1.js', '-m'], false); + const { exitCode, stderr, stdout } = run(__dirname, ['--config', './1.js', '--merge'], false); expect(exitCode).toBe(2); expect(stderr).toContain('At least two configurations are required for merge.'); diff --git a/test/merge/config/second-entry.js b/test/merge/config/second-entry.js new file mode 100644 index 00000000000..e1595dffb00 --- /dev/null +++ b/test/merge/config/second-entry.js @@ -0,0 +1 @@ +console.log('second'); diff --git a/test/merge/config/some_entry.js b/test/merge/config/some_entry.js deleted file mode 100644 index ad5fca8a5fd..00000000000 --- a/test/merge/config/some_entry.js +++ /dev/null @@ -1 +0,0 @@ -console.log('yass'); diff --git a/test/merge/config/third-entry.js b/test/merge/config/third-entry.js new file mode 100644 index 00000000000..29134430a5e --- /dev/null +++ b/test/merge/config/third-entry.js @@ -0,0 +1 @@ +console.log('third'); From 2841cd77284678dfccc500f8c6e1eb509c9c7aff Mon Sep 17 00:00:00 2001 From: Rishabh Chawla Date: Tue, 2 Feb 2021 20:06:22 +0530 Subject: [PATCH 27/29] test: default loader name and plugin name (#2392) --- test/loader/loader.test.js | 28 ++++++++++++++++++++++++++++ test/plugin/plugin.test.js | 27 +++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/test/loader/loader.test.js b/test/loader/loader.test.js index bf1638a239d..6ee115a8853 100644 --- a/test/loader/loader.test.js +++ b/test/loader/loader.test.js @@ -10,11 +10,13 @@ const firstPrompt = '? Loader name (my-loader)'; const ENTER = '\x0D'; const loaderName = 'test-loader'; const loaderPath = join(__dirname, loaderName); +const defaultLoaderPath = join(__dirname, 'my-loader'); const genPath = join(__dirname, 'test-assets'); const customLoaderPath = join(genPath, loaderName); describe('loader command', () => { beforeEach(() => { + rimraf.sync(defaultLoaderPath); rimraf.sync(loaderPath); rimraf.sync(genPath); }); @@ -26,6 +28,32 @@ describe('loader command', () => { expect(stripAnsi(stdout)).toContain(firstPrompt); }); + it('should scaffold loader with default name if no loader name provided', async () => { + let { stdout } = await runPromptWithAnswers(__dirname, ['loader'], [`${ENTER}`]); + + expect(stripAnsi(stdout)).toContain(firstPrompt); + + // Skip test in case installation fails + if (!existsSync(resolve(defaultLoaderPath, './yarn.lock'))) { + return; + } + + // Check if the output directory exists with the appropriate loader name + expect(existsSync(defaultLoaderPath)).toBeTruthy(); + + // All test files are scaffolded + const files = ['package.json', 'examples', 'src', 'test', 'src/index.js', 'examples/simple/webpack.config.js']; + + files.forEach((file) => { + expect(existsSync(defaultLoaderPath, file)).toBeTruthy(); + }); + + // Check if the the generated loader works successfully + const path = resolve(__dirname, './my-loader/examples/simple/'); + ({ stdout } = run(path, [], false)); + expect(stdout).toContain('my-loader'); + }); + it('should scaffold loader template with a given name', async () => { let { stdout } = await runPromptWithAnswers(__dirname, ['loader'], [`${loaderName}${ENTER}`]); diff --git a/test/plugin/plugin.test.js b/test/plugin/plugin.test.js index ac41d218dd6..bad234e7a83 100644 --- a/test/plugin/plugin.test.js +++ b/test/plugin/plugin.test.js @@ -10,11 +10,13 @@ const firstPrompt = '? Plugin name'; const pluginName = 'test-plugin'; const pluginPath = join(__dirname, pluginName); +const defaultPluginPath = join(__dirname, 'my-webpack-plugin'); const genPath = join(__dirname, 'test-assets'); const customPluginPath = join(genPath, pluginName); describe('plugin command', () => { beforeEach(() => { + rimraf.sync(defaultPluginPath); rimraf.sync(pluginPath); rimraf.sync(genPath); }); @@ -26,6 +28,31 @@ describe('plugin command', () => { expect(stripAnsi(stdout)).toContain(firstPrompt); }); + it('should scaffold plugin with default name if no plugin name provided', async () => { + let { stdout } = await runPromptWithAnswers(__dirname, ['plugin'], [`${ENTER}`]); + + expect(stripAnsi(stdout)).toContain(firstPrompt); + + // Check if the output directory exists with the appropriate plugin name + expect(existsSync(defaultPluginPath)).toBeTruthy(); + + // Skip test in case installation fails + if (!existsSync(resolve(defaultPluginPath, './yarn.lock'))) { + return; + } + + // Test regressively files are scaffolded + const files = ['package.json', 'examples', 'src', 'test', 'src/index.js', 'examples/simple/webpack.config.js']; + + files.forEach((file) => { + expect(existsSync(join(defaultPluginPath, file))).toBeTruthy(); + }); + + // Check if the the generated plugin works successfully + stdout = run(__dirname, ['--config', './my-webpack-plugin/examples/simple/webpack.config.js'], false).stdout; + expect(stdout).toContain('Hello World!'); + }); + it('should scaffold plugin template with a given name', async () => { let { stdout } = await runPromptWithAnswers(__dirname, ['plugin'], [`${pluginName}${ENTER}`]); From e5126f10b6622437c0541c25be2a610a82c1df04 Mon Sep 17 00:00:00 2001 From: Nitin Kumar Date: Tue, 2 Feb 2021 20:59:51 +0530 Subject: [PATCH 28/29] feat: add the `--node-env` flag (#2388) --- packages/webpack-cli/lib/webpack-cli.js | 16 +++++++- test/node-env/auto-mode.config.js | 5 +++ test/node-env/node-env.test.js | 53 +++++++++++++++++++++++++ test/node-env/src/index.js | 1 + test/node-env/webpack.config.js | 6 +++ 5 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 test/node-env/auto-mode.config.js create mode 100644 test/node-env/node-env.test.js create mode 100644 test/node-env/src/index.js create mode 100644 test/node-env/webpack.config.js diff --git a/packages/webpack-cli/lib/webpack-cli.js b/packages/webpack-cli/lib/webpack-cli.js index 79f7070534c..15be68263dc 100644 --- a/packages/webpack-cli/lib/webpack-cli.js +++ b/packages/webpack-cli/lib/webpack-cli.js @@ -295,6 +295,12 @@ class WebpackCLI { multiple: true, description: 'Environment passed to the configuration when it is a function.', }, + { + name: 'node-env', + type: String, + multiple: false, + description: 'Sets process.env.NODE_ENV to the specified value', + }, // Adding more plugins { @@ -429,6 +435,12 @@ class WebpackCLI { return options; } + applyNodeEnv(options) { + if (typeof options.nodeEnv === 'string') { + process.env.NODE_ENV = options.nodeEnv; + } + } + async run(args, parseOptions) { // Built-in internal commands const buildCommandOptions = { @@ -1517,7 +1529,7 @@ class WebpackCLI { !configOptions.mode && process.env && process.env.NODE_ENV && - (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'node') + (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'none') ) { configOptions.mode = process.env.NODE_ENV; } @@ -1653,6 +1665,8 @@ class WebpackCLI { } async createCompiler(options, callback) { + this.applyNodeEnv(options); + let config = await this.resolveConfig(options); config = await this.applyOptions(config, options); diff --git a/test/node-env/auto-mode.config.js b/test/node-env/auto-mode.config.js new file mode 100644 index 00000000000..385cb2ac035 --- /dev/null +++ b/test/node-env/auto-mode.config.js @@ -0,0 +1,5 @@ +const WebpackCLITestPlugin = require('../utils/webpack-cli-test-plugin'); + +module.exports = { + plugins: [new WebpackCLITestPlugin()], +}; diff --git a/test/node-env/node-env.test.js b/test/node-env/node-env.test.js new file mode 100644 index 00000000000..4d8bda5d328 --- /dev/null +++ b/test/node-env/node-env.test.js @@ -0,0 +1,53 @@ +'use strict'; + +const { run } = require('../utils/test-utils'); + +describe('--node-env flag', () => { + it('should set "process.env.NODE_ENV" to "development"', () => { + const { exitCode, stderr, stdout } = run(__dirname, ['--node-env', 'development']); + + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toContain("mode: 'development'"); + }); + + it('should set "process.env.NODE_ENV" to "production"', () => { + const { exitCode, stderr, stdout } = run(__dirname, ['--node-env', 'production']); + + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toContain("mode: 'production'"); + }); + + it('should set "process.env.NODE_ENV" to "none"', () => { + const { exitCode, stderr, stdout } = run(__dirname, ['--node-env', 'none']); + + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toContain("mode: 'none'"); + }); + + it('should set "process.env.NODE_ENV" and the "mode" option to "development"', () => { + const { exitCode, stderr, stdout } = run(__dirname, ['--node-env', 'development', '--config', './auto-mode.config.js']); + + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toContain("mode: 'development'"); + }); + + it('should set "process.env.NODE_ENV" and the "mode" option to "production"', () => { + const { exitCode, stderr, stdout } = run(__dirname, ['--node-env', 'production', '--config', './auto-mode.config.js']); + + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toContain("mode: 'production'"); + }); + + it('should set "process.env.NODE_ENV" and the "mode" option to "none"', () => { + const { exitCode, stderr, stdout } = run(__dirname, ['--node-env', 'none', '--config', './auto-mode.config.js']); + + expect(exitCode).toBe(0); + expect(stderr).toBeFalsy(); + expect(stdout).toContain("mode: 'none'"); + }); +}); diff --git a/test/node-env/src/index.js b/test/node-env/src/index.js new file mode 100644 index 00000000000..c70a2899e94 --- /dev/null +++ b/test/node-env/src/index.js @@ -0,0 +1 @@ +console.log('--node-env test'); \ No newline at end of file diff --git a/test/node-env/webpack.config.js b/test/node-env/webpack.config.js new file mode 100644 index 00000000000..ca74229899d --- /dev/null +++ b/test/node-env/webpack.config.js @@ -0,0 +1,6 @@ +const WebpackCLITestPlugin = require('../utils/webpack-cli-test-plugin'); + +module.exports = { + mode: process.env.NODE_ENV, + plugins: [new WebpackCLITestPlugin()], +}; From 3bbda71e9637b7d20f3f49f9e080e27d8d8ae929 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Tue, 2 Feb 2021 20:03:06 +0300 Subject: [PATCH 29/29] chore(release): publish new version - @webpack-cli/configtest@1.0.1 - @webpack-cli/generators@1.3.1 - @webpack-cli/info@1.2.2 - @webpack-cli/init@1.1.3 - @webpack-cli/serve@1.3.0 - webpack-cli@4.5.0 --- packages/configtest/CHANGELOG.md | 6 ++++++ packages/configtest/package.json | 2 +- packages/generators/CHANGELOG.md | 4 ++++ packages/generators/package.json | 2 +- packages/info/CHANGELOG.md | 4 ++++ packages/info/package.json | 2 +- packages/init/CHANGELOG.md | 4 ++++ packages/init/package.json | 4 ++-- packages/serve/CHANGELOG.md | 11 +++++++++++ packages/serve/package.json | 2 +- packages/webpack-cli/CHANGELOG.md | 14 ++++++++++++++ packages/webpack-cli/package.json | 8 ++++---- 12 files changed, 53 insertions(+), 10 deletions(-) diff --git a/packages/configtest/CHANGELOG.md b/packages/configtest/CHANGELOG.md index 5b94c2f2ba8..5591b28d520 100644 --- a/packages/configtest/CHANGELOG.md +++ b/packages/configtest/CHANGELOG.md @@ -3,6 +3,12 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.0.1](https://github.com/webpack/webpack-cli/compare/@webpack-cli/configtest@1.0.0...@webpack-cli/configtest@1.0.1) (2021-02-02) + +### Bug Fixes + +- improve description for 'configtest' command ([#2379](https://github.com/webpack/webpack-cli/issues/2379)) ([311bae3](https://github.com/webpack/webpack-cli/commit/311bae336d83424c800e553b6ef40242d967685c)) + # 1.0.0 (2021-01-19) ### Features diff --git a/packages/configtest/package.json b/packages/configtest/package.json index b33a1bd3d15..e1edb626ad1 100644 --- a/packages/configtest/package.json +++ b/packages/configtest/package.json @@ -1,6 +1,6 @@ { "name": "@webpack-cli/configtest", - "version": "1.0.0", + "version": "1.0.1", "description": "Validate a webpack configuration.", "main": "lib/index.js", "types": "lib/index.d.ts", diff --git a/packages/generators/CHANGELOG.md b/packages/generators/CHANGELOG.md index c273131aa0c..21a61d8b8b7 100644 --- a/packages/generators/CHANGELOG.md +++ b/packages/generators/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.3.1](https://github.com/webpack/webpack-cli/compare/@webpack-cli/generators@1.3.0...@webpack-cli/generators@1.3.1) (2021-02-02) + +**Note:** Version bump only for package @webpack-cli/generators + # [1.3.0](https://github.com/webpack/webpack-cli/compare/@webpack-cli/generators@1.2.1...@webpack-cli/generators@1.3.0) (2021-01-19) ### Bug Fixes diff --git a/packages/generators/package.json b/packages/generators/package.json index 518d16009c6..8984a335af8 100644 --- a/packages/generators/package.json +++ b/packages/generators/package.json @@ -1,6 +1,6 @@ { "name": "@webpack-cli/generators", - "version": "1.3.0", + "version": "1.3.1", "description": "Webpack-CLI generators", "main": "lib/index.js", "types": "lib/index.d.ts", diff --git a/packages/info/CHANGELOG.md b/packages/info/CHANGELOG.md index 32c830bbc58..6d94a300ed5 100644 --- a/packages/info/CHANGELOG.md +++ b/packages/info/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.2.2](https://github.com/webpack/webpack-cli/compare/@webpack-cli/info@1.2.1...@webpack-cli/info@1.2.2) (2021-02-02) + +**Note:** Version bump only for package @webpack-cli/info + ## [1.2.1](https://github.com/webpack/webpack-cli/compare/@webpack-cli/info@1.2.0...@webpack-cli/info@1.2.1) (2020-12-31) ### Bug Fixes diff --git a/packages/info/package.json b/packages/info/package.json index dbb837959a5..e46b874587d 100644 --- a/packages/info/package.json +++ b/packages/info/package.json @@ -1,6 +1,6 @@ { "name": "@webpack-cli/info", - "version": "1.2.1", + "version": "1.2.2", "description": "Outputs info about system and webpack config", "main": "lib/index.js", "types": "lib/index.d.ts", diff --git a/packages/init/CHANGELOG.md b/packages/init/CHANGELOG.md index 71ce0af5f2a..890c797cfe5 100644 --- a/packages/init/CHANGELOG.md +++ b/packages/init/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.1.3](https://github.com/webpack/webpack-cli/compare/@webpack-cli/init@1.1.2...@webpack-cli/init@1.1.3) (2021-02-02) + +**Note:** Version bump only for package @webpack-cli/init + ## [1.1.2](https://github.com/webpack/webpack-cli/compare/@webpack-cli/init@1.1.1...@webpack-cli/init@1.1.2) (2021-01-19) **Note:** Version bump only for package @webpack-cli/init diff --git a/packages/init/package.json b/packages/init/package.json index 9f4261998c6..92ce11d2b7d 100644 --- a/packages/init/package.json +++ b/packages/init/package.json @@ -1,6 +1,6 @@ { "name": "@webpack-cli/init", - "version": "1.1.2", + "version": "1.1.3", "description": "init command for webpack-cli", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -12,7 +12,7 @@ "lib" ], "dependencies": { - "@webpack-cli/generators": "^1.3.0" + "@webpack-cli/generators": "^1.3.1" }, "peerDependencies": { "webpack": "4.x.x || 5.x.x", diff --git a/packages/serve/CHANGELOG.md b/packages/serve/CHANGELOG.md index 6df9f1652e1..1410db8f934 100644 --- a/packages/serve/CHANGELOG.md +++ b/packages/serve/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [1.3.0](https://github.com/webpack/webpack-cli/compare/@webpack-cli/serve@1.2.2...@webpack-cli/serve@1.3.0) (2021-02-02) + +### Bug Fixes + +- avoid deprecation message ([9d6dbda](https://github.com/webpack/webpack-cli/commit/9d6dbda93da167a1aaad03f599105a4fe7849dc3)) +- error message on invalid plugin options ([#2380](https://github.com/webpack/webpack-cli/issues/2380)) ([f9ce1d3](https://github.com/webpack/webpack-cli/commit/f9ce1d30b83bf0e0b4d91498d012c13c208e6e67)) + +### Features + +- entries syntax ([#2369](https://github.com/webpack/webpack-cli/issues/2369)) ([6b31614](https://github.com/webpack/webpack-cli/commit/6b3161479578f572f803f579c7e71073eb797184)) + ## [1.2.2](https://github.com/webpack/webpack-cli/compare/@webpack-cli/serve@1.2.1...@webpack-cli/serve@1.2.2) (2021-01-19) ### Bug Fixes diff --git a/packages/serve/package.json b/packages/serve/package.json index 55426cbfbe7..de003324058 100644 --- a/packages/serve/package.json +++ b/packages/serve/package.json @@ -1,6 +1,6 @@ { "name": "@webpack-cli/serve", - "version": "1.2.2", + "version": "1.3.0", "description": "", "main": "lib/index.js", "types": "lib/index.d.ts", diff --git a/packages/webpack-cli/CHANGELOG.md b/packages/webpack-cli/CHANGELOG.md index 7ae81a01387..cd541473b01 100644 --- a/packages/webpack-cli/CHANGELOG.md +++ b/packages/webpack-cli/CHANGELOG.md @@ -3,6 +3,20 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [4.5.0](https://github.com/webpack/webpack-cli/compare/webpack-cli@4.4.0...webpack-cli@4.5.0) (2021-02-02) + +### Bug Fixes + +- avoid deprecation message ([9d6dbda](https://github.com/webpack/webpack-cli/commit/9d6dbda93da167a1aaad03f599105a4fe7849dc3)) +- error message on invalid plugin options ([#2380](https://github.com/webpack/webpack-cli/issues/2380)) ([f9ce1d3](https://github.com/webpack/webpack-cli/commit/f9ce1d30b83bf0e0b4d91498d012c13c208e6e67)) +- improve description for 'configtest' command ([#2379](https://github.com/webpack/webpack-cli/issues/2379)) ([311bae3](https://github.com/webpack/webpack-cli/commit/311bae336d83424c800e553b6ef40242d967685c)) + +### Features + +- add the `--node-env` flag ([#2388](https://github.com/webpack/webpack-cli/issues/2388)) ([e5126f1](https://github.com/webpack/webpack-cli/commit/e5126f10b6622437c0541c25be2a610a82c1df04)) +- entries syntax ([#2369](https://github.com/webpack/webpack-cli/issues/2369)) ([6b31614](https://github.com/webpack/webpack-cli/commit/6b3161479578f572f803f579c7e71073eb797184)) +- support ES module configuration format ([#2381](https://github.com/webpack/webpack-cli/issues/2381)) ([aebdbbc](https://github.com/webpack/webpack-cli/commit/aebdbbc1f6e2761e7821cb3660bea686cce7b587)) + # [4.4.0](https://github.com/webpack/webpack-cli/compare/webpack-cli@4.3.1...webpack-cli@4.4.0) (2021-01-19) ### Bug Fixes diff --git a/packages/webpack-cli/package.json b/packages/webpack-cli/package.json index bbeea374eba..a81232c5aa6 100644 --- a/packages/webpack-cli/package.json +++ b/packages/webpack-cli/package.json @@ -1,6 +1,6 @@ { "name": "webpack-cli", - "version": "4.4.0", + "version": "4.5.0", "description": "CLI for webpack & friends", "license": "MIT", "repository": { @@ -28,9 +28,9 @@ ], "dependencies": { "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^1.0.0", - "@webpack-cli/info": "^1.2.1", - "@webpack-cli/serve": "^1.2.2", + "@webpack-cli/configtest": "^1.0.1", + "@webpack-cli/info": "^1.2.2", + "@webpack-cli/serve": "^1.3.0", "colorette": "^1.2.1", "commander": "^7.0.0", "enquirer": "^2.3.6",