diff --git a/packages/webpack-cli/README.md b/packages/webpack-cli/README.md index f1bfe4fb9a3..1b230155ee6 100644 --- a/packages/webpack-cli/README.md +++ b/packages/webpack-cli/README.md @@ -37,7 +37,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 + -c, --config string[] Provide path to webpack configuration file(s) --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 diff --git a/packages/webpack-cli/lib/groups/ConfigGroup.js b/packages/webpack-cli/lib/groups/ConfigGroup.js index 09f4cea3f3b..90e8e91bcec 100644 --- a/packages/webpack-cli/lib/groups/ConfigGroup.js +++ b/packages/webpack-cli/lib/groups/ConfigGroup.js @@ -143,18 +143,34 @@ class ConfigGroup extends GroupHelper { async resolveConfigFiles() { const { config, mode } = this.args; - if (config) { - const configPath = resolve(process.cwd(), config); - const configFiles = getConfigInfoFromFileName(configPath); - if (!configFiles.length) { - throw new ConfigError(`The specified config file doesn't exist in ${configPath}`); + if (config.length > 0) { + const resolvedOptions = []; + const finalizedConfigs = config.map(async (webpackConfig) => { + const configPath = resolve(webpackConfig); + const configFiles = getConfigInfoFromFileName(configPath); + if (!configFiles.length) { + throw new ConfigError(`The specified config file doesn't exist in ${configPath}`); + } + const foundConfig = configFiles[0]; + const resolvedConfig = this.requireConfig(foundConfig); + return this.finalize(resolvedConfig); + }); + // resolve all the configs + for await (const resolvedOption of finalizedConfigs) { + if (Array.isArray(resolvedOption.options)) { + resolvedOptions.push(...resolvedOption.options); + } else { + resolvedOptions.push(resolvedOption.options); + } } - const foundConfig = configFiles[0]; - const resolvedConfig = this.requireConfig(foundConfig); - this.opts = await this.finalize(resolvedConfig); + // When the resolved configs are more than 1, then pass them as Array [{...}, {...}] else pass the first config object {...} + const finalOptions = resolvedOptions.length > 1 ? resolvedOptions : resolvedOptions[0] || {}; + + this.opts['options'] = finalOptions; return; } + // When no config is supplied, lookup for default configs const defaultConfigFiles = getDefaultConfigFiles(); const tmpConfigFiles = defaultConfigFiles.filter((file) => { return existsSync(file.path); @@ -175,9 +191,8 @@ class ConfigGroup extends GroupHelper { async resolveConfigMerging() { // eslint-disable-next-line no-prototype-builtins - if (Object.keys(this.args).some((arg) => arg === 'merge')) { - const { merge } = this.args; - + const { merge } = this.args; + if (merge) { // try resolving merge config const newConfigPath = this.resolveFilePath(merge); @@ -189,7 +204,17 @@ class ConfigGroup extends GroupHelper { const foundConfig = configFiles[0]; const resolvedConfig = this.requireConfig(foundConfig); const newConfigurationsObject = await this.finalize(resolvedConfig); - this.opts['options'] = webpackMerge(this.opts['options'], newConfigurationsObject.options); + let resolvedOptions = this.opts['options']; + let mergedOptions; + if (Array.isArray(resolvedOptions)) { + mergedOptions = []; + resolvedOptions.forEach((resolvedOption) => { + mergedOptions.push(webpackMerge(resolvedOption, newConfigurationsObject.options)); + }); + } else { + mergedOptions = webpackMerge(resolvedOptions, newConfigurationsObject.options); + } + this.opts['options'] = mergedOptions; } } diff --git a/packages/webpack-cli/lib/utils/cli-flags.js b/packages/webpack-cli/lib/utils/cli-flags.js index e7b59cee01a..c372293756b 100644 --- a/packages/webpack-cli/lib/utils/cli-flags.js +++ b/packages/webpack-cli/lib/utils/cli-flags.js @@ -91,8 +91,9 @@ const core = [ usage: '--config ', alias: 'c', type: String, - defaultValue: null, + defaultValue: [], group: CONFIG_GROUP, + multiple: true, description: 'Provide path to a webpack configuration file e.g. ./webpack.config.js', link: 'https://webpack.js.org/configuration/', }, diff --git a/test/config/multiple/all/.webpack/webpack.config.dev.js b/test/config/defaults/all/.webpack/webpack.config.dev.js similarity index 100% rename from test/config/multiple/all/.webpack/webpack.config.dev.js rename to test/config/defaults/all/.webpack/webpack.config.dev.js diff --git a/test/config/multiple/all/.webpack/webpack.config.none.js b/test/config/defaults/all/.webpack/webpack.config.none.js similarity index 100% rename from test/config/multiple/all/.webpack/webpack.config.none.js rename to test/config/defaults/all/.webpack/webpack.config.none.js diff --git a/test/config/multiple/all/.webpack/webpack.config.prod.js b/test/config/defaults/all/.webpack/webpack.config.prod.js similarity index 100% rename from test/config/multiple/all/.webpack/webpack.config.prod.js rename to test/config/defaults/all/.webpack/webpack.config.prod.js diff --git a/test/config/multiple/all/index.js b/test/config/defaults/all/index.js similarity index 100% rename from test/config/multiple/all/index.js rename to test/config/defaults/all/index.js diff --git a/test/config/multiple/all/multiple-config.test.js b/test/config/defaults/all/multiple-config.test.js similarity index 91% rename from test/config/multiple/all/multiple-config.test.js rename to test/config/defaults/all/multiple-config.test.js index 23a36fcd554..793a4a93403 100644 --- a/test/config/multiple/all/multiple-config.test.js +++ b/test/config/defaults/all/multiple-config.test.js @@ -3,7 +3,7 @@ const { stat } = require('fs'); const { resolve } = require('path'); const { run } = require('../../../utils/test-utils'); -describe('multiple config files', () => { +describe('Default configuration files: ', () => { it('Uses prod config from dot folder if present', (done) => { const { stdout, stderr } = run(__dirname, [], false); expect(stderr).toBeFalsy(); diff --git a/test/config/multiple/multiple-location/.webpack/webpack.config.development.js b/test/config/defaults/multiple-location/.webpack/webpack.config.development.js similarity index 100% rename from test/config/multiple/multiple-location/.webpack/webpack.config.development.js rename to test/config/defaults/multiple-location/.webpack/webpack.config.development.js diff --git a/test/config/multiple/multiple-location/index.js b/test/config/defaults/multiple-location/index.js similarity index 100% rename from test/config/multiple/multiple-location/index.js rename to test/config/defaults/multiple-location/index.js diff --git a/test/config/multiple/multiple-location/multiple-location-config.test.js b/test/config/defaults/multiple-location/multiple-location-config.test.js similarity index 100% rename from test/config/multiple/multiple-location/multiple-location-config.test.js rename to test/config/defaults/multiple-location/multiple-location-config.test.js diff --git a/test/config/multiple/multiple-location/webpack.config.development.js b/test/config/defaults/multiple-location/webpack.config.development.js similarity index 100% rename from test/config/multiple/multiple-location/webpack.config.development.js rename to test/config/defaults/multiple-location/webpack.config.development.js diff --git a/test/config/multiple/multiple-location/webpack.config.js b/test/config/defaults/multiple-location/webpack.config.js similarity index 100% rename from test/config/multiple/multiple-location/webpack.config.js rename to test/config/defaults/multiple-location/webpack.config.js diff --git a/test/config/multiple/none and dev/.webpack/webpack.config.dev.js b/test/config/defaults/none and dev/.webpack/webpack.config.dev.js similarity index 100% rename from test/config/multiple/none and dev/.webpack/webpack.config.dev.js rename to test/config/defaults/none and dev/.webpack/webpack.config.dev.js diff --git a/test/config/multiple/none and dev/.webpack/webpack.config.none.js b/test/config/defaults/none and dev/.webpack/webpack.config.none.js similarity index 100% rename from test/config/multiple/none and dev/.webpack/webpack.config.none.js rename to test/config/defaults/none and dev/.webpack/webpack.config.none.js diff --git a/test/config/multiple/none and dev/dev-none-config.test.js b/test/config/defaults/none and dev/dev-none-config.test.js similarity index 100% rename from test/config/multiple/none and dev/dev-none-config.test.js rename to test/config/defaults/none and dev/dev-none-config.test.js diff --git a/test/config/multiple/none and dev/index.js b/test/config/defaults/none and dev/index.js similarity index 100% rename from test/config/multiple/none and dev/index.js rename to test/config/defaults/none and dev/index.js diff --git a/test/config/multiple/with-mode/index.js b/test/config/defaults/with-mode/index.js similarity index 100% rename from test/config/multiple/with-mode/index.js rename to test/config/defaults/with-mode/index.js diff --git a/test/config/multiple/with-mode/multiple-config.test.js b/test/config/defaults/with-mode/multiple-config.test.js similarity index 100% rename from test/config/multiple/with-mode/multiple-config.test.js rename to test/config/defaults/with-mode/multiple-config.test.js diff --git a/test/config/multiple/with-mode/webpack.config.development.js b/test/config/defaults/with-mode/webpack.config.development.js similarity index 100% rename from test/config/multiple/with-mode/webpack.config.development.js rename to test/config/defaults/with-mode/webpack.config.development.js diff --git a/test/config/multiple/with-mode/webpack.config.none.js b/test/config/defaults/with-mode/webpack.config.none.js similarity index 100% rename from test/config/multiple/with-mode/webpack.config.none.js rename to test/config/defaults/with-mode/webpack.config.none.js diff --git a/test/config/multiple/with-mode/webpack.config.production.js b/test/config/defaults/with-mode/webpack.config.production.js similarity index 100% rename from test/config/multiple/with-mode/webpack.config.production.js rename to test/config/defaults/with-mode/webpack.config.production.js diff --git a/test/config/multiple/init.js b/test/config/multiple/init.js new file mode 100644 index 00000000000..63e43c10599 --- /dev/null +++ b/test/config/multiple/init.js @@ -0,0 +1 @@ +console.log('Monkey D Luffy'); diff --git a/test/config/multiple/multiple-config.test.js b/test/config/multiple/multiple-config.test.js new file mode 100644 index 00000000000..f040031bdbc --- /dev/null +++ b/test/config/multiple/multiple-config.test.js @@ -0,0 +1,21 @@ +const { existsSync } = require('fs'); +const { resolve } = require('path'); +// eslint-disable-next-line node/no-missing-require +const { run } = require('../../utils/test-utils'); + +describe('Multiple config flag: ', () => { + it('spawns multiple compilers for multiple configs', () => { + const { stdout, stderr, exitCode } = run(__dirname, ['-c', 'webpack1.config.js', '-c', 'webpack2.config.js'], false); + // Should contain the correct exit code + expect(exitCode).toEqual(0); + // Should spawn multiple compilers + expect(stdout).toContain('Child amd:'); + expect(stdout).toContain('Child commonjs:'); + + expect(stderr).toBeFalsy(); + + // should generate the correct output files + expect(existsSync(resolve(__dirname, './dist/dist-commonjs.js'))).toBeTruthy(); + expect(existsSync(resolve(__dirname, './dist/dist-amd.js'))).toBeTruthy(); + }); +}); diff --git a/test/config/multiple/webpack1.config.js b/test/config/multiple/webpack1.config.js new file mode 100644 index 00000000000..788a7689cdf --- /dev/null +++ b/test/config/multiple/webpack1.config.js @@ -0,0 +1,10 @@ +module.exports = { + output: { + filename: './dist-amd.js', + libraryTarget: 'amd', + }, + name: 'amd', + entry: './init.js', + mode: 'production', + devtool: 'eval-cheap-module-source-map', +}; diff --git a/test/config/multiple/webpack2.config.js b/test/config/multiple/webpack2.config.js new file mode 100644 index 00000000000..efa5ecd44ad --- /dev/null +++ b/test/config/multiple/webpack2.config.js @@ -0,0 +1,10 @@ +module.exports = { + output: { + filename: './dist-commonjs.js', + libraryTarget: 'commonjs', + }, + name: 'commonjs', + entry: './init.js', + mode: 'production', + target: 'node', +}; diff --git a/test/config/type/function-with-argv/function-with-argv.test.js b/test/config/type/function-with-argv/function-with-argv.test.js index d13de6a1944..06498c156f5 100644 --- a/test/config/type/function-with-argv/function-with-argv.test.js +++ b/test/config/type/function-with-argv/function-with-argv.test.js @@ -8,7 +8,7 @@ describe('function configuration', () => { const { stderr, stdout } = run(__dirname, ['--mode', 'development'], false); expect(stderr).toBeFalsy(); expect(stdout).toBeTruthy(); - expect(stdout).toContain("argv: { config: null, color: true, mode: 'development' }"); + expect(stdout).toContain("argv: { config: [], color: true, mode: 'development' }"); // Should generate the appropriate files expect(existsSync(resolve(__dirname, './dist/dev.js'))).toBeTruthy(); });