diff --git a/packages/webpack-cli/__tests__/ConfigGroup/env.webpack.config.cjs b/packages/webpack-cli/__tests__/resolveConfig/env.webpack.config.cjs similarity index 100% rename from packages/webpack-cli/__tests__/ConfigGroup/env.webpack.config.cjs rename to packages/webpack-cli/__tests__/resolveConfig/env.webpack.config.cjs diff --git a/packages/webpack-cli/__tests__/ConfigGroup/ConfigGroup.test.js b/packages/webpack-cli/__tests__/resolveConfig/resolveConfig.test.js similarity index 82% rename from packages/webpack-cli/__tests__/ConfigGroup/ConfigGroup.test.js rename to packages/webpack-cli/__tests__/resolveConfig/resolveConfig.test.js index f82ba382478..4ad49dfab67 100644 --- a/packages/webpack-cli/__tests__/ConfigGroup/ConfigGroup.test.js +++ b/packages/webpack-cli/__tests__/resolveConfig/resolveConfig.test.js @@ -1,13 +1,13 @@ -const ConfigGroup = require('../../lib/groups/ConfigGroup'); +const resolveConfig = require('../../lib/groups/resolveConfig.js'); const { resolve } = require('path'); const config1 = require('./webpack.config1.cjs'); const config2 = require('./webpack.config2.cjs'); const arrayConfig = require('./webpack.config.cjs'); const promiseConfig = require('./webpack.promise.config.cjs'); -describe('ConfigGroup', function () { +describe('resolveConfig', function () { it('should handle merge properly', async () => { - const result = await ConfigGroup({ + const result = await resolveConfig({ merge: true, config: [resolve(__dirname, './webpack.config.cjs')], }); @@ -25,7 +25,7 @@ describe('ConfigGroup', function () { }); it('should return array for multiple config', async () => { - const result = await ConfigGroup({ + const result = await resolveConfig({ config: [resolve(__dirname, './webpack.config1.cjs'), resolve(__dirname, './webpack.config2.cjs')], }); const expectedOptions = [config1, config2]; @@ -34,20 +34,20 @@ describe('ConfigGroup', function () { }); it('should return config object for single config', async () => { - const result = await ConfigGroup({ config: [resolve(__dirname, './webpack.config1.cjs')] }); + const result = await resolveConfig({ config: [resolve(__dirname, './webpack.config1.cjs')] }); expect(result.options).toEqual(config1); expect(result.outputOptions).toEqual({}); }); it('should return resolved config object for promise config', async () => { - const result = await ConfigGroup({ config: [resolve(__dirname, './webpack.promise.config.cjs')] }); + const result = await resolveConfig({ config: [resolve(__dirname, './webpack.promise.config.cjs')] }); const expectedOptions = await promiseConfig(); expect(result.options).toEqual(expectedOptions); expect(result.outputOptions).toEqual({}); }); it('should handle configs returning different types', async () => { - const result = await ConfigGroup({ + const result = await resolveConfig({ config: [resolve(__dirname, './webpack.promise.config.cjs'), resolve(__dirname, './webpack.config.cjs')], }); const resolvedPromiseConfig = await promiseConfig(); @@ -57,7 +57,7 @@ describe('ConfigGroup', function () { }); it('should handle different env formats', async () => { - const result = await ConfigGroup({ + const result = await resolveConfig({ env: { test: true, name: 'Hisoka' }, config: [resolve(__dirname, './env.webpack.config.cjs')], }); diff --git a/packages/webpack-cli/__tests__/ConfigGroup/webpack.config.cjs b/packages/webpack-cli/__tests__/resolveConfig/webpack.config.cjs similarity index 100% rename from packages/webpack-cli/__tests__/ConfigGroup/webpack.config.cjs rename to packages/webpack-cli/__tests__/resolveConfig/webpack.config.cjs diff --git a/packages/webpack-cli/__tests__/ConfigGroup/webpack.config1.cjs b/packages/webpack-cli/__tests__/resolveConfig/webpack.config1.cjs similarity index 100% rename from packages/webpack-cli/__tests__/ConfigGroup/webpack.config1.cjs rename to packages/webpack-cli/__tests__/resolveConfig/webpack.config1.cjs diff --git a/packages/webpack-cli/__tests__/ConfigGroup/webpack.config2.cjs b/packages/webpack-cli/__tests__/resolveConfig/webpack.config2.cjs similarity index 100% rename from packages/webpack-cli/__tests__/ConfigGroup/webpack.config2.cjs rename to packages/webpack-cli/__tests__/resolveConfig/webpack.config2.cjs diff --git a/packages/webpack-cli/__tests__/ConfigGroup/webpack.promise.config.cjs b/packages/webpack-cli/__tests__/resolveConfig/webpack.promise.config.cjs similarity index 100% rename from packages/webpack-cli/__tests__/ConfigGroup/webpack.promise.config.cjs rename to packages/webpack-cli/__tests__/resolveConfig/webpack.promise.config.cjs diff --git a/packages/webpack-cli/lib/groups/ConfigGroup.js b/packages/webpack-cli/lib/groups/resolveConfig.js similarity index 95% rename from packages/webpack-cli/lib/groups/ConfigGroup.js rename to packages/webpack-cli/lib/groups/resolveConfig.js index beac89662e8..ed66ebcca1c 100644 --- a/packages/webpack-cli/lib/groups/ConfigGroup.js +++ b/packages/webpack-cli/lib/groups/resolveConfig.js @@ -156,7 +156,9 @@ const finalize = async (moduleObj, args) => { const isMultiCompilerMode = Array.isArray(config); const rawConfigs = isMultiCompilerMode ? config : [config]; - let configs = await Promise.all( + let configs = []; + + const allConfigs = await Promise.all( rawConfigs.map(async (rawConfig) => { const isPromise = typeof rawConfig.then === 'function'; @@ -174,6 +176,14 @@ const finalize = async (moduleObj, args) => { }), ); + for (const singleConfig of allConfigs) { + if (Array.isArray(singleConfig)) { + configs.push(...singleConfig); + } else { + configs.push(singleConfig); + } + } + if (configName) { const foundConfigNames = []; @@ -204,7 +214,7 @@ const finalize = async (moduleObj, args) => { process.exit(2); } - newOptionsObject['options'] = isMultiCompilerMode ? configs : configs[0]; + newOptionsObject['options'] = configs.length > 1 ? configs : configs[0]; return newOptionsObject; }; diff --git a/packages/webpack-cli/lib/webpack-cli.js b/packages/webpack-cli/lib/webpack-cli.js index 7ea5eef84ce..918af585ebf 100644 --- a/packages/webpack-cli/lib/webpack-cli.js +++ b/packages/webpack-cli/lib/webpack-cli.js @@ -11,7 +11,7 @@ const { options: coloretteOptions } = require('colorette'); const WebpackCLIPlugin = require('./plugins/WebpackCLIPlugin'); // CLI arg resolvers -const handleConfigResolution = require('./groups/ConfigGroup'); +const handleConfigResolution = require('./groups/resolveConfig'); const resolveMode = require('./groups/resolveMode'); const resolveStats = require('./groups/resolveStats'); const resolveOutput = require('./groups/resolveOutput'); diff --git a/test/config-name/config-name.test.js b/test/config-name/config-name.test.js index de2fe509af4..deee81523b7 100644 --- a/test/config-name/config-name.test.js +++ b/test/config-name/config-name.test.js @@ -81,4 +81,51 @@ describe('--config-name flag', () => { expect(stdout).toBeFalsy(); expect(exitCode).toBe(2); }); + + it('should work with config as a function', (done) => { + const { stderr, stdout, exitCode } = run(__dirname, ['--config', 'function-config.js', '--config-name', 'first'], false); + expect(stderr).toBeFalsy(); + expect(stdout).toContain('first'); + expect(stdout).not.toContain('second'); + expect(stdout).not.toContain('third'); + expect(exitCode).toBe(0); + + 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 when the config is a function', (done) => { + const { stderr, stdout, exitCode } = run( + __dirname, + ['--config', 'function-config.js', '--config-name', 'first', '--config-name', 'third'], + false, + ); + expect(stderr).toBeFalsy(); + expect(stdout).toContain('first'); + expect(stdout).not.toContain('second'); + expect(stdout).toContain('third'); + expect(exitCode).toBe(0); + + stat(resolve(__dirname, './dist/dist-third.js'), (err, stats) => { + expect(err).toBe(null); + expect(stats.isFile()).toBe(true); + + stat(resolve(__dirname, './dist/dist-first.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, exitCode } = run(__dirname, ['--config', 'function-config.js', '--config-name', 'test'], false); + + expect(stderr).toContain('Configuration with name "test" was not found.'); + expect(stdout).toBeFalsy(); + expect(exitCode).toBe(2); + }); }); diff --git a/test/config-name/function-config.js b/test/config-name/function-config.js new file mode 100644 index 00000000000..ff198656a45 --- /dev/null +++ b/test/config-name/function-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', + }, +]; diff --git a/test/config-name/webpack.config.js b/test/config-name/webpack.config.js index 4580e6062d0..3504fa3ae9b 100644 --- a/test/config-name/webpack.config.js +++ b/test/config-name/webpack.config.js @@ -6,7 +6,6 @@ module.exports = [ name: 'first', entry: './src/first.js', mode: 'development', - stats: 'minimal', }, { output: { @@ -15,7 +14,6 @@ module.exports = [ name: 'second', entry: './src/second.js', mode: 'production', - stats: 'minimal', }, { output: { diff --git a/test/config/function/functional-config.test.js b/test/config/function/functional-config.test.js new file mode 100644 index 00000000000..ccc79d6aec1 --- /dev/null +++ b/test/config/function/functional-config.test.js @@ -0,0 +1,40 @@ +'use strict'; +const { resolve } = require('path'); +const { stat } = require('fs'); +const { run } = require('../../utils/test-utils'); + +describe('functional config', () => { + it('should work as expected in case of single config', (done) => { + const { stderr, stdout, exitCode } = run(__dirname, ['--config', resolve(__dirname, 'single-webpack.config.js')]); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain('./src/index.js'); + expect(exitCode).toBe(0); + + stat(resolve(__dirname, './bin/dist-single.js'), (err, stats) => { + expect(err).toBe(null); + expect(stats.isFile()).toBe(true); + done(); + }); + }); + + it('should work as expected in case of multiple config', (done) => { + const { stderr, stdout, exitCode } = run(__dirname, ['--config', resolve(__dirname, 'multi-webpack.config.js')]); + + expect(stderr).toBeFalsy(); + expect(stdout).toContain('first'); + expect(stdout).toContain('second'); + expect(exitCode).toBe(0); + + stat(resolve(__dirname, './bin/dist-first.js'), (err, stats) => { + expect(err).toBe(null); + expect(stats.isFile()).toBe(true); + done(); + }); + stat(resolve(__dirname, './bin/dist-second.js'), (err, stats) => { + expect(err).toBe(null); + expect(stats.isFile()).toBe(true); + done(); + }); + }); +}); diff --git a/test/config/function/multi-webpack.config.js b/test/config/function/multi-webpack.config.js new file mode 100644 index 00000000000..1ea167bf529 --- /dev/null +++ b/test/config/function/multi-webpack.config.js @@ -0,0 +1,20 @@ +module.exports = () => [ + { + output: { + filename: './dist-first.js', + }, + name: 'first', + entry: './src/first.js', + mode: 'development', + stats: 'minimal', + }, + { + output: { + filename: './dist-second.js', + }, + name: 'second', + entry: './src/second.js', + mode: 'production', + stats: 'minimal', + }, +]; diff --git a/test/config/function/single-webpack.config.js b/test/config/function/single-webpack.config.js new file mode 100644 index 00000000000..dbf14dc44c9 --- /dev/null +++ b/test/config/function/single-webpack.config.js @@ -0,0 +1,9 @@ +module.exports = () => { + return { + output: { + filename: './dist-single.js', + }, + name: 'single', + mode: 'development', + }; +}; diff --git a/test/config/function/src/first.js b/test/config/function/src/first.js new file mode 100644 index 00000000000..5a33e8ffd02 --- /dev/null +++ b/test/config/function/src/first.js @@ -0,0 +1 @@ +console.log('first entry'); diff --git a/test/config/function/src/index.js b/test/config/function/src/index.js new file mode 100644 index 00000000000..398f16d07ee --- /dev/null +++ b/test/config/function/src/index.js @@ -0,0 +1 @@ +console.log('default index'); diff --git a/test/config/function/src/second.js b/test/config/function/src/second.js new file mode 100644 index 00000000000..3ce234df055 --- /dev/null +++ b/test/config/function/src/second.js @@ -0,0 +1 @@ +console.log('second entry');