diff --git a/packages/webpack-cli/README.md b/packages/webpack-cli/README.md index 4751e251fec..637ac81ea74 100644 --- a/packages/webpack-cli/README.md +++ b/packages/webpack-cli/README.md @@ -38,6 +38,7 @@ yarn add webpack-cli --dev ``` --entry string[] The entry point(s) of your application. -c, --config string Provide path to a webpack configuration file + --config-name string[] Name of the configuration to use -m, --merge string Merge a configuration file using webpack-merge --progress Print compilation progress during build --color Enables colors on console diff --git a/packages/webpack-cli/lib/groups/ConfigGroup.js b/packages/webpack-cli/lib/groups/ConfigGroup.js index 5e8953759be..0850feaf5b4 100644 --- a/packages/webpack-cli/lib/groups/ConfigGroup.js +++ b/packages/webpack-cli/lib/groups/ConfigGroup.js @@ -5,6 +5,7 @@ const { extensions, jsVariants } = require('interpret'); const GroupHelper = require('../utils/GroupHelper'); const rechoir = require('rechoir'); const MergeError = require('../utils/errors/MergeError'); +const logger = require('../utils/logger'); // Order defines the priority, in increasing order // example - config file lookup will be in order of .webpack/webpack.config.development.js -> webpack.config.development.js -> webpack.config.js @@ -117,6 +118,16 @@ class ConfigGroup extends GroupHelper { const newOptions = configOptions(formattedEnv, argv); // When config function returns a promise, resolve it, if not it's resolved by default newOptionsObject['options'] = await Promise.resolve(newOptions); + } else if (Array.isArray(configOptions) && this.args.configName) { + // In case of exporting multiple configurations, If you pass a name to --config-name flag, + // webpack will only build that specific configuration. + const namedOptions = configOptions.filter((opt) => this.args.configName.includes(opt.name)); + if (namedOptions.length === 0) { + logger.error(`Configuration with name "${this.args.configName}" was not found.`); + process.exit(1); + } else { + newOptionsObject['options'] = namedOptions; + } } else { if (Array.isArray(configOptions) && !configOptions.length) { newOptionsObject['options'] = {}; diff --git a/packages/webpack-cli/lib/utils/cli-flags.js b/packages/webpack-cli/lib/utils/cli-flags.js index b11a1debb08..0e4afea8193 100644 --- a/packages/webpack-cli/lib/utils/cli-flags.js +++ b/packages/webpack-cli/lib/utils/cli-flags.js @@ -124,6 +124,14 @@ module.exports = { description: 'Provide path to a webpack configuration file e.g. ./webpack.config.js', link: 'https://webpack.js.org/configuration/', }, + { + name: 'config-name', + usage: '--config-name ', + type: String, + multiple: true, + group: CONFIG_GROUP, + description: 'Name of the configuration to use', + }, { name: 'color', usage: '--color', diff --git a/test/config-name/config-name.test.js b/test/config-name/config-name.test.js new file mode 100644 index 00000000000..53b66537ecf --- /dev/null +++ b/test/config-name/config-name.test.js @@ -0,0 +1,46 @@ +'use strict'; + +const { run } = require('../utils/test-utils'); +const { stat } = require('fs'); +const { resolve } = require('path'); + +describe('--config-name flag', () => { + it('should select only the config whose name is passed with --config-name', (done) => { + const { stderr, stdout } = run(__dirname, ['--config-name', 'first'], false); + expect(stderr).toBeFalsy(); + expect(stdout).toContain('Child first'); + expect(stdout).not.toContain('Child second'); + expect(stdout).not.toContain('Child third'); + + stat(resolve(__dirname, './dist/dist-first.js'), (err, stats) => { + expect(err).toBe(null); + expect(stats.isFile()).toBe(true); + done(); + }); + }); + + it('should work with multiple values for --config-name', (done) => { + const { stderr, stdout } = run(__dirname, ['--config-name', 'first', '--config-name', 'third'], false); + expect(stderr).toBeFalsy(); + expect(stdout).toContain('Child first'); + expect(stdout).not.toContain('Child second'); + expect(stdout).toContain('Child third'); + + stat(resolve(__dirname, './dist/dist-first.js'), (err, stats) => { + expect(err).toBe(null); + expect(stats.isFile()).toBe(true); + done(); + }); + stat(resolve(__dirname, './dist/dist-third.js'), (err, stats) => { + expect(err).toBe(null); + expect(stats.isFile()).toBe(true); + done(); + }); + }); + + it('should log error if invalid config name is provided', () => { + const { stderr, stdout } = run(__dirname, ['--config-name', 'test'], false); + expect(stderr).toContain('Configuration with name "test" was not found.'); + expect(stdout).toBeFalsy(); + }); +}); diff --git a/test/config-name/src/first.js b/test/config-name/src/first.js new file mode 100644 index 00000000000..3dfd0a1def0 --- /dev/null +++ b/test/config-name/src/first.js @@ -0,0 +1 @@ +console.log('first config'); diff --git a/test/config-name/src/second.js b/test/config-name/src/second.js new file mode 100644 index 00000000000..15c0f734c34 --- /dev/null +++ b/test/config-name/src/second.js @@ -0,0 +1 @@ +console.log('second config'); diff --git a/test/config-name/src/third.js b/test/config-name/src/third.js new file mode 100644 index 00000000000..1047ae56bdc --- /dev/null +++ b/test/config-name/src/third.js @@ -0,0 +1 @@ +console.log('third config'); diff --git a/test/config-name/webpack.config.js b/test/config-name/webpack.config.js new file mode 100644 index 00000000000..515d077d3e2 --- /dev/null +++ b/test/config-name/webpack.config.js @@ -0,0 +1,26 @@ +module.exports = [ + { + output: { + filename: './dist-first.js', + }, + name: 'first', + entry: './src/first.js', + mode: 'development', + }, + { + output: { + filename: './dist-second.js', + }, + name: 'second', + entry: './src/second.js', + mode: 'production', + }, + { + output: { + filename: './dist-third.js', + }, + name: 'third', + entry: './src/third.js', + mode: 'none', + }, +];