From 69723c785f6dad565e848b88faebe75011980866 Mon Sep 17 00:00:00 2001 From: homer0 Date: Fri, 30 Aug 2019 06:36:11 -0300 Subject: [PATCH 1/3] feat(services/building/configuration): reduce the configuration params using an event --- src/services/building/configuration.js | 21 +- tests/services/building/configuration.test.js | 307 ++++++++++++------ 2 files changed, 217 insertions(+), 111 deletions(-) diff --git a/src/services/building/configuration.js b/src/services/building/configuration.js index 89d566e..8b17823 100644 --- a/src/services/building/configuration.js +++ b/src/services/building/configuration.js @@ -66,11 +66,17 @@ class WebpackConfiguration { } /** * This method generates a complete webpack configuration for a target. - * @param {Target} target The target information. - * @param {string} buildType The intended build type: `production` or `development`. + * Before creating the configuration, it uses the reducer event + * `webpack-configuration-parameters-for-browser` or `webpack-configuration-parameters-for-node`, + * depending on the target type, and then `webpack-configuration-parameters` to reduce + * the parameters ({@link WebpackConfigurationParams}) the services will use to generate the + * configuration. The event recevies the parameters and expects updated parameters in return. + * @param {Target} target The target information. + * @param {string} buildType The intended build type: `production` or `development`. * @return {Object} * @throws {Error} If there's no base configuration for the target type. * @throws {Error} If there's no base configuration for the target type and build type. + * @todo Stop using `events` from `targets` and inject it directly on the class. */ getConfig(target, buildType) { const targetType = target.type; @@ -99,7 +105,7 @@ class WebpackConfiguration { const definitions = this._getDefinitionsGenerator(target, buildType); const additionalWatch = this._getBrowserTargetConfigurationDefinitions(target).files; - const params = { + let params = { target, targetRules: this.targetsFileRules.getRulesForTarget(target), entry: { @@ -117,6 +123,15 @@ class WebpackConfiguration { analyze: !!target.analyze, }; + const eventName = params.target.is.node ? + 'webpack-configuration-parameters-for-node' : + 'webpack-configuration-parameters-for-browser'; + + params = this.targets.events.reduce( + [eventName, 'webpack-configuration-parameters'], + params + ); + let config = this.targetConfiguration( `webpack/${target.name}.config.js`, this.webpackConfigurations[targetType][buildType] diff --git a/tests/services/building/configuration.test.js b/tests/services/building/configuration.test.js index c650b54..fcbcdb5 100644 --- a/tests/services/building/configuration.test.js +++ b/tests/services/building/configuration.test.js @@ -126,12 +126,16 @@ describe('services/building:configuration', () => { const targetConfig = { getConfig: jest.fn(() => config), }; + const events = { + reduce: jest.fn((eventName, configParams) => configParams), + }; const envVarName = 'ROSARIO'; const envVarValue = 'Charito'; const targets = { loadTargetDotEnvFile: jest.fn(() => ({ [envVarName]: envVarValue, })), + events, }; const targetRules = 'target-rule'; const targetsFileRules = { @@ -173,6 +177,21 @@ describe('services/building:configuration', () => { let result = null; let definitionsGenerator = null; let generatedDefinitions = null; + const expectedParams = { + target, + buildType, + entry: { + [target.name]: [path.join(target.paths.source, target.entry[buildType])], + }, + definitions: expect.any(Function), + output: Object.assign({}, target.output[buildType], { + jsChunks: target.output[buildType].js.replace(/\.js$/, '.[name].js'), + }), + targetRules, + copy: [], + additionalWatch: [], + analyze: false, + }; // When sut = new WebpackConfiguration( buildVersion, @@ -209,23 +228,17 @@ describe('services/building:configuration', () => { expect(targets.loadTargetDotEnvFile).toHaveBeenCalledTimes(1); expect(targets.loadTargetDotEnvFile).toHaveBeenCalledWith(target, buildType); expect(targetConfig.getConfig).toHaveBeenCalledTimes(1); - expect(targetConfig.getConfig).toHaveBeenCalledWith({ - target, - buildType, - entry: { - [target.name]: [path.join(target.paths.source, target.entry[buildType])], - }, - definitions: expect.any(Function), - output: Object.assign({}, target.output[buildType], { - jsChunks: target.output[buildType].js.replace(/\.js$/, '.[name].js'), - }), - targetRules, - copy: [], - additionalWatch: [], - analyze: false, - }); + expect(targetConfig.getConfig).toHaveBeenCalledWith(expectedParams); expect(pathUtils.join).toHaveBeenCalledTimes(1); expect(pathUtils.join).toHaveBeenCalledWith(config.output.path); + expect(events.reduce).toHaveBeenCalledTimes(1); + expect(events.reduce).toHaveBeenCalledWith( + [ + 'webpack-configuration-parameters-for-node', + 'webpack-configuration-parameters', + ], + expectedParams + ); }); it('should generate the configuration for a Node target that requires bundling', () => { @@ -247,10 +260,14 @@ describe('services/building:configuration', () => { const targetConfig = { getConfig: jest.fn(() => config), }; + const events = { + reduce: jest.fn((eventName, configParams) => configParams), + }; const filesToCopy = ['copy']; const targets = { getFilesToCopy: jest.fn(() => filesToCopy), loadTargetDotEnvFile: jest.fn(() => ({})), + events, }; const targetRules = 'target-rule'; const targetsFileRules = { @@ -291,6 +308,21 @@ describe('services/building:configuration', () => { const webpackPluginInfo = 'webpackPluginInfo'; let sut = null; let result = null; + const expectedParams = { + target, + buildType, + entry: { + [target.name]: [path.join(target.paths.source, target.entry[buildType])], + }, + definitions: expect.any(Function), + output: Object.assign({}, target.output[buildType], { + jsChunks: target.output[buildType].js.replace(/\.js$/, '.[name].js'), + }), + targetRules, + copy: filesToCopy, + additionalWatch: [], + analyze: false, + }; // When sut = new WebpackConfiguration( buildVersion, @@ -319,25 +351,19 @@ describe('services/building:configuration', () => { ); expect(targets.loadTargetDotEnvFile).toHaveBeenCalledTimes(0); expect(targetConfig.getConfig).toHaveBeenCalledTimes(1); - expect(targetConfig.getConfig).toHaveBeenCalledWith({ - target, - buildType, - entry: { - [target.name]: [path.join(target.paths.source, target.entry[buildType])], - }, - definitions: expect.any(Function), - output: Object.assign({}, target.output[buildType], { - jsChunks: target.output[buildType].js.replace(/\.js$/, '.[name].js'), - }), - targetRules, - copy: filesToCopy, - additionalWatch: [], - analyze: false, - }); + expect(targetConfig.getConfig).toHaveBeenCalledWith(expectedParams); expect(pathUtils.join).toHaveBeenCalledTimes(1); expect(pathUtils.join).toHaveBeenCalledWith(config.output.path); expect(targets.getFilesToCopy).toHaveBeenCalledTimes(1); expect(targets.getFilesToCopy).toHaveBeenCalledWith(target, buildType); + expect(events.reduce).toHaveBeenCalledTimes(1); + expect(events.reduce).toHaveBeenCalledWith( + [ + 'webpack-configuration-parameters-for-node', + 'webpack-configuration-parameters', + ], + expectedParams + ); }); it('should generate the configuration for a browser target', () => { @@ -361,10 +387,14 @@ describe('services/building:configuration', () => { const targetConfig = { getConfig: jest.fn(() => config), }; + const events = { + reduce: jest.fn((eventName, configParams) => configParams), + }; const filesToCopy = ['copy']; const targets = { getFilesToCopy: jest.fn(() => filesToCopy), loadTargetDotEnvFile: jest.fn(() => ({})), + events, }; const targetRules = 'target-rule'; const targetsFileRules = { @@ -405,6 +435,19 @@ describe('services/building:configuration', () => { const webpackPluginInfo = 'webpackPluginInfo'; let sut = null; let result = null; + const expectedParams = { + target, + buildType, + entry: { + [target.name]: [path.join(target.paths.source, target.entry[buildType])], + }, + definitions: expect.any(Function), + output: target.output[buildType], + targetRules, + copy: filesToCopy, + additionalWatch: [], + analyze: false, + }; // When sut = new WebpackConfiguration( buildVersion, @@ -431,23 +474,19 @@ describe('services/building:configuration', () => { ); expect(targets.loadTargetDotEnvFile).toHaveBeenCalledTimes(0); expect(targetConfig.getConfig).toHaveBeenCalledTimes(1); - expect(targetConfig.getConfig).toHaveBeenCalledWith({ - target, - buildType, - entry: { - [target.name]: [path.join(target.paths.source, target.entry[buildType])], - }, - definitions: expect.any(Function), - output: target.output[buildType], - targetRules, - copy: filesToCopy, - additionalWatch: [], - analyze: false, - }); + expect(targetConfig.getConfig).toHaveBeenCalledWith(expectedParams); expect(pathUtils.join).toHaveBeenCalledTimes(1); expect(pathUtils.join).toHaveBeenCalledWith(config.output.path); expect(targets.getFilesToCopy).toHaveBeenCalledTimes(1); expect(targets.getFilesToCopy).toHaveBeenCalledWith(target, buildType); + expect(events.reduce).toHaveBeenCalledTimes(1); + expect(events.reduce).toHaveBeenCalledWith( + [ + 'webpack-configuration-parameters-for-browser', + 'webpack-configuration-parameters', + ], + expectedParams + ); }); it('should generate the configuration for a browser target and `define` its config', () => { @@ -469,6 +508,9 @@ describe('services/building:configuration', () => { const targetConfig = { getConfig: jest.fn(() => config), }; + const events = { + reduce: jest.fn((eventName, configParams) => configParams), + }; const targetBrowserConfig = { someProp: 'someValue', }; @@ -481,6 +523,7 @@ describe('services/building:configuration', () => { configuration: targetBrowserConfig, files: targetBrowserConfigFiles, })), + events, }; const targetRules = 'target-rule'; const targetsFileRules = { @@ -522,6 +565,21 @@ describe('services/building:configuration', () => { let result = null; let definitionsGenerator = null; let generatedDefinitions = null; + const expectedParams = { + target, + buildType, + entry: { + [target.name]: [path.join(target.paths.source, target.entry[buildType])], + }, + output: Object.assign({}, target.output[buildType], { + jsChunks: target.output[buildType].js.replace(/\.js$/, '.[name].js'), + }), + definitions: expect.any(Function), + targetRules, + copy: filesToCopy, + additionalWatch: targetBrowserConfigFiles, + analyze: false, + }; // When sut = new WebpackConfiguration( buildVersion, @@ -556,21 +614,7 @@ describe('services/building:configuration', () => { expect(targets.loadTargetDotEnvFile).toHaveBeenCalledTimes(1); expect(targets.loadTargetDotEnvFile).toHaveBeenCalledWith(target, buildType); expect(targetConfig.getConfig).toHaveBeenCalledTimes(1); - expect(targetConfig.getConfig).toHaveBeenCalledWith({ - target, - buildType, - entry: { - [target.name]: [path.join(target.paths.source, target.entry[buildType])], - }, - output: Object.assign({}, target.output[buildType], { - jsChunks: target.output[buildType].js.replace(/\.js$/, '.[name].js'), - }), - definitions: expect.any(Function), - targetRules, - copy: filesToCopy, - additionalWatch: targetBrowserConfigFiles, - analyze: false, - }); + expect(targetConfig.getConfig).toHaveBeenCalledWith(expectedParams); expect(pathUtils.join).toHaveBeenCalledTimes(1); expect(pathUtils.join).toHaveBeenCalledWith(config.output.path); expect(targets.getFilesToCopy).toHaveBeenCalledTimes(1); @@ -578,6 +622,14 @@ describe('services/building:configuration', () => { expect(targets.getBrowserTargetConfiguration).toHaveBeenCalledTimes(2); expect(targets.getBrowserTargetConfiguration).toHaveBeenCalledWith(target); expect(targets.getBrowserTargetConfiguration).toHaveBeenCalledWith(target); + expect(events.reduce).toHaveBeenCalledTimes(1); + expect(events.reduce).toHaveBeenCalledWith( + [ + 'webpack-configuration-parameters-for-browser', + 'webpack-configuration-parameters', + ], + expectedParams + ); }); it('should generate the configuration for a target, with the Babel polyfill', () => { @@ -599,8 +651,12 @@ describe('services/building:configuration', () => { const targetConfig = { getConfig: jest.fn(() => config), }; + const events = { + reduce: jest.fn((eventName, configParams) => configParams), + }; const targets = { loadTargetDotEnvFile: jest.fn(() => ({})), + events, }; const targetRules = 'target-rule'; const targetsFileRules = { @@ -645,6 +701,24 @@ describe('services/building:configuration', () => { }; let sut = null; let result = null; + const expectedParams = { + target, + buildType, + entry: { + [target.name]: [ + `${webpackPluginInfo.name}/${webpackPluginInfo.babelPolyfill}`, + path.join(target.paths.source, target.entry[buildType]), + ], + }, + definitions: expect.any(Function), + output: Object.assign({}, target.output[buildType], { + jsChunks: target.output[buildType].js.replace(/\.js$/, '.[name].js'), + }), + targetRules, + copy: [], + additionalWatch: [], + analyze: false, + }; // When sut = new WebpackConfiguration( buildVersion, @@ -671,26 +745,17 @@ describe('services/building:configuration', () => { ); expect(targets.loadTargetDotEnvFile).toHaveBeenCalledTimes(0); expect(targetConfig.getConfig).toHaveBeenCalledTimes(1); - expect(targetConfig.getConfig).toHaveBeenCalledWith({ - target, - buildType, - entry: { - [target.name]: [ - `${webpackPluginInfo.name}/${webpackPluginInfo.babelPolyfill}`, - path.join(target.paths.source, target.entry[buildType]), - ], - }, - definitions: expect.any(Function), - output: Object.assign({}, target.output[buildType], { - jsChunks: target.output[buildType].js.replace(/\.js$/, '.[name].js'), - }), - targetRules, - copy: [], - additionalWatch: [], - analyze: false, - }); + expect(targetConfig.getConfig).toHaveBeenCalledWith(expectedParams); expect(pathUtils.join).toHaveBeenCalledTimes(1); expect(pathUtils.join).toHaveBeenCalledWith(config.output.path); + expect(events.reduce).toHaveBeenCalledTimes(1); + expect(events.reduce).toHaveBeenCalledWith( + [ + 'webpack-configuration-parameters-for-node', + 'webpack-configuration-parameters', + ], + expectedParams + ); }); it('should generate the configuration for a library target', () => { @@ -712,8 +777,12 @@ describe('services/building:configuration', () => { const targetConfig = { getConfig: jest.fn(() => config), }; + const events = { + reduce: jest.fn((eventName, configParams) => configParams), + }; const targets = { loadTargetDotEnvFile: jest.fn(() => ({})), + events, }; const targetRules = 'target-rule'; const targetsFileRules = { @@ -760,6 +829,21 @@ describe('services/building:configuration', () => { }; let sut = null; let result = null; + const expectedParams = { + target, + buildType, + entry: { + [target.name]: [path.join(target.paths.source, target.entry[buildType])], + }, + definitions: expect.any(Function), + output: Object.assign({}, target.output[buildType], { + jsChunks: target.output[buildType].js.replace(/\.js$/, '.[name].js'), + }), + targetRules, + copy: [], + additionalWatch: [], + analyze: false, + }; // When sut = new WebpackConfiguration( buildVersion, @@ -786,23 +870,17 @@ describe('services/building:configuration', () => { ); expect(targets.loadTargetDotEnvFile).toHaveBeenCalledTimes(0); expect(targetConfig.getConfig).toHaveBeenCalledTimes(1); - expect(targetConfig.getConfig).toHaveBeenCalledWith({ - target, - buildType, - entry: { - [target.name]: [path.join(target.paths.source, target.entry[buildType])], - }, - definitions: expect.any(Function), - output: Object.assign({}, target.output[buildType], { - jsChunks: target.output[buildType].js.replace(/\.js$/, '.[name].js'), - }), - targetRules, - copy: [], - additionalWatch: [], - analyze: false, - }); + expect(targetConfig.getConfig).toHaveBeenCalledWith(expectedParams); expect(pathUtils.join).toHaveBeenCalledTimes(1); expect(pathUtils.join).toHaveBeenCalledWith(config.output.path); + expect(events.reduce).toHaveBeenCalledTimes(1); + expect(events.reduce).toHaveBeenCalledWith( + [ + 'webpack-configuration-parameters-for-node', + 'webpack-configuration-parameters', + ], + expectedParams + ); }); it('should generate the configuration for a library target and remove unsupported keys', () => { @@ -824,8 +902,12 @@ describe('services/building:configuration', () => { const targetConfig = { getConfig: jest.fn(() => config), }; + const events = { + reduce: jest.fn((eventName, configParams) => configParams), + }; const targets = { loadTargetDotEnvFile: jest.fn(() => ({})), + events, }; const targetRules = 'target-rule'; const targetsFileRules = { @@ -866,14 +948,29 @@ describe('services/building:configuration', () => { }, }; const webpackPluginInfo = 'webpackPluginInfo'; + let sut = null; + let result = null; const expectedConfig = { output: { path: 'some-output-path', libraryTarget: 'commonjs2', }, }; - let sut = null; - let result = null; + const expectedParams = { + target, + buildType, + entry: { + [target.name]: [path.join(target.paths.source, target.entry[buildType])], + }, + definitions: expect.any(Function), + output: Object.assign({}, target.output[buildType], { + jsChunks: target.output[buildType].js.replace(/\.js$/, '.[name].js'), + }), + targetRules, + copy: [], + additionalWatch: [], + analyze: false, + }; // When sut = new WebpackConfiguration( buildVersion, @@ -900,23 +997,17 @@ describe('services/building:configuration', () => { ); expect(targets.loadTargetDotEnvFile).toHaveBeenCalledTimes(0); expect(targetConfig.getConfig).toHaveBeenCalledTimes(1); - expect(targetConfig.getConfig).toHaveBeenCalledWith({ - target, - buildType, - entry: { - [target.name]: [path.join(target.paths.source, target.entry[buildType])], - }, - definitions: expect.any(Function), - output: Object.assign({}, target.output[buildType], { - jsChunks: target.output[buildType].js.replace(/\.js$/, '.[name].js'), - }), - targetRules, - copy: [], - additionalWatch: [], - analyze: false, - }); + expect(targetConfig.getConfig).toHaveBeenCalledWith(expectedParams); expect(pathUtils.join).toHaveBeenCalledTimes(1); expect(pathUtils.join).toHaveBeenCalledWith(config.output.path); + expect(events.reduce).toHaveBeenCalledTimes(1); + expect(events.reduce).toHaveBeenCalledWith( + [ + 'webpack-configuration-parameters-for-node', + 'webpack-configuration-parameters', + ], + expectedParams + ); }); it('should include a provider for the DIC', () => { From 19634a7679eb5febb1ff6e8581c314cb84c31e0f Mon Sep 17 00:00:00 2001 From: homer0 Date: Fri, 30 Aug 2019 06:36:42 -0300 Subject: [PATCH 2/3] docs(project): update the README with all the 'params' and the new events --- README.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 981d2b2..04a9980 100644 --- a/README.md +++ b/README.md @@ -120,8 +120,11 @@ All the configurations receive a single object parameter with the following prop - `targetRules`: The rules to find the target files on the file system. - `entry`: A dictionary with the `entry` setting for a webpack configuration, generated with the target information. - `output`: A dictionary with the filenames formats and paths of the different files the bundle can generate (`js`, `css`, `images` and `fonts`). -- `definitions`: A dictionary of defined variables that will be replaced on the bundled code. +- `definitions`: A function that generates a dictionary of variables that will be replaced on the bundled code. - `buildType`: The indented build type (`development` or `production`). +- `copy`: A list of information for files that need to be copied during the bundling process. +- `additionalWatch`: A list of additional paths webpack should watch for in order to restart the bundle. +- `analyze`: A flag to detect if the bundled should be analyzed or not. #### Base configuration @@ -233,6 +236,13 @@ Now, this plugin only uses the loader if the implementation has `image-webpack-l If you want to write a plugin that works with this one (like a framework plugin), there are a lot of reducer events you can listen for and use to modify the webpack configuration: +### Configuration parameters + +- Name: `webpack-configuration-parameters` +- Reduces: The parameters used by the plugin services to build a target configuration. + +This is called before generating any configuration. + ### Node target configuration - Name: `webpack-base-configuration-for-node` From 858466fbe935ad7cf3dcc239412d5ed2b7ad3a31 Mon Sep 17 00:00:00 2001 From: homer0 Date: Fri, 30 Aug 2019 06:37:05 -0300 Subject: [PATCH 3/3] v9.2.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bda3d60..c409978 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "projext-plugin-webpack", "description": "Allows projext to use webpack as a build engine.", "homepage": "https://homer0.github.io/projext-plugin-webpack/", - "version": "9.1.0", + "version": "9.2.0", "repository": "homer0/projext-plugin-webpack", "author": "Leonardo Apiwan (@homer0) ", "license": "MIT",