From f4459da26923131d38177ce9cbf95773e958a9e9 Mon Sep 17 00:00:00 2001 From: Anshuman Verma Date: Fri, 6 Nov 2020 20:56:07 +0530 Subject: [PATCH] fix: move resolveArgs to CLI instance --- ...olveOutput.test.js => resolveArgs.test.js} | 4 +- .../webpack-cli/lib/groups/basicResolver.js | 142 ----------------- packages/webpack-cli/lib/utils/arg-parser.js | 1 - packages/webpack-cli/lib/webpack-cli.js | 150 +++++++++++++++++- 4 files changed, 146 insertions(+), 151 deletions(-) rename packages/webpack-cli/__tests__/{resolveOutput.test.js => resolveArgs.test.js} (97%) delete mode 100644 packages/webpack-cli/lib/groups/basicResolver.js diff --git a/packages/webpack-cli/__tests__/resolveOutput.test.js b/packages/webpack-cli/__tests__/resolveArgs.test.js similarity index 97% rename from packages/webpack-cli/__tests__/resolveOutput.test.js rename to packages/webpack-cli/__tests__/resolveArgs.test.js index 30ae69b10e9..d5347ba23fd 100644 --- a/packages/webpack-cli/__tests__/resolveOutput.test.js +++ b/packages/webpack-cli/__tests__/resolveArgs.test.js @@ -1,8 +1,10 @@ const { resolve } = require('path'); -const basicResolver = require('../lib/groups/basicResolver'); +const webpackCLI = require('../lib/webpack-cli'); const targetValues = ['web', 'webworker', 'node', 'async-node', 'node-webkit', 'electron-main', 'electron-renderer', 'electron-preload']; +const basicResolver = new webpackCLI().resolveArgs; + describe('BasicResolver', () => { it('should handle the output option', async () => { const result = await basicResolver({ diff --git a/packages/webpack-cli/lib/groups/basicResolver.js b/packages/webpack-cli/lib/groups/basicResolver.js deleted file mode 100644 index 28e91825d4f..00000000000 --- a/packages/webpack-cli/lib/groups/basicResolver.js +++ /dev/null @@ -1,142 +0,0 @@ -const path = require('path'); -const { core, groups } = require('../utils/cli-flags'); -const packageExists = require('../utils/package-exists'); -const promptInstallation = require('../utils/prompt-installation'); -const { yellow } = require('colorette'); -const { error, success } = require('../utils/logger'); - -const WEBPACK_OPTION_FLAGS = core - .filter((coreFlag) => { - return coreFlag.group === groups.BASIC_GROUP; - }) - .reduce((result, flagObject) => { - result.push(flagObject.name); - if (flagObject.alias) { - result.push(flagObject.alias); - } - return result; - }, []); - -const PRODUCTION = 'production'; -const DEVELOPMENT = 'development'; - -/* - Mode priority: - - Mode flag - - Mode from config - - Mode form NODE_ENV - */ -/** - * - * @param {string} mode - mode flag value - * @param {Object} configObject - contains relevant loaded config - */ -const assignMode = (mode, configObject) => { - const { - env: { NODE_ENV }, - } = process; - const { mode: configMode } = configObject; - let finalMode; - if (mode) { - finalMode = mode; - } else if (configMode) { - finalMode = configMode; - } else if (NODE_ENV && (NODE_ENV === PRODUCTION || NODE_ENV === DEVELOPMENT)) { - finalMode = NODE_ENV; - } else { - finalMode = PRODUCTION; - } - return finalMode; -}; - -const resolveArgs = async (args, configOptions = {}) => { - const { outputPath, stats, json, mode, target, prefetch, hot, analyze } = args; - - const finalOptions = { - options: {}, - outputOptions: {}, - }; - Object.keys(args).forEach((arg) => { - if (WEBPACK_OPTION_FLAGS.includes(arg)) { - finalOptions.outputOptions[arg] = args[arg]; - } - if (arg === 'devtool') { - finalOptions.options.devtool = args[arg]; - } - if (arg === 'name') { - finalOptions.options.name = args[arg]; - } - if (arg === 'watch') { - finalOptions.options.watch = true; - } - if (arg === 'entry') { - finalOptions.options[arg] = args[arg]; - } - }); - if (outputPath) { - finalOptions.options.output = { path: path.resolve(outputPath) }; - } - - if (stats !== undefined) { - finalOptions.options.stats = stats; - } - if (json) { - finalOptions.outputOptions.json = json; - } - - if (hot) { - const { HotModuleReplacementPlugin } = require('webpack'); - const hotModuleVal = new HotModuleReplacementPlugin(); - if (finalOptions.options && finalOptions.options.plugins) { - finalOptions.options.plugins.unshift(hotModuleVal); - } else { - finalOptions.options.plugins = [hotModuleVal]; - } - } - if (prefetch) { - const { PrefetchPlugin } = require('webpack'); - const prefetchVal = new PrefetchPlugin(null, args.prefetch); - if (finalOptions.options && finalOptions.options.plugins) { - finalOptions.options.plugins.unshift(prefetchVal); - } else { - finalOptions.options.plugins = [prefetchVal]; - } - } - if (analyze) { - if (packageExists('webpack-bundle-analyzer')) { - // eslint-disable-next-line node/no-extraneous-require - const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); - const bundleAnalyzerVal = new BundleAnalyzerPlugin(); - if (finalOptions.options && finalOptions.options.plugins) { - finalOptions.options.plugins.unshift(bundleAnalyzerVal); - } else { - finalOptions.options.plugins = [bundleAnalyzerVal]; - } - } else { - await promptInstallation('webpack-bundle-analyzer', () => { - error(`It looks like ${yellow('webpack-bundle-analyzer')} is not installed.`); - }) - .then(() => success(`${yellow('webpack-bundle-analyzer')} was installed sucessfully.`)) - .catch(() => { - error(`Action Interrupted, Please try once again or install ${yellow('webpack-bundle-analyzer')} manually.`); - process.exit(2); - }); - } - } - if (target) { - finalOptions.options.target = args.target; - } - - if (Array.isArray(configOptions)) { - // Todo - handle multi config for all flags - finalOptions.options = configOptions.map(() => ({ ...finalOptions.options })); - configOptions.forEach((configObject, index) => { - finalOptions.options[index].mode = assignMode(mode, configObject); - }); - } else { - finalOptions.options.mode = assignMode(mode, configOptions); - } - return finalOptions; -}; - -module.exports = resolveArgs; diff --git a/packages/webpack-cli/lib/utils/arg-parser.js b/packages/webpack-cli/lib/utils/arg-parser.js index dd239e6e2b2..73dbfb350c0 100644 --- a/packages/webpack-cli/lib/utils/arg-parser.js +++ b/packages/webpack-cli/lib/utils/arg-parser.js @@ -16,7 +16,6 @@ const { defaultCommands } = require('./cli-flags'); */ const argParser = (options, args, argsOnly = false, name = '') => { const parser = new commander.Command(); - // Set parser name parser.name(name); parser.storeOptionsAsProperties(false); diff --git a/packages/webpack-cli/lib/webpack-cli.js b/packages/webpack-cli/lib/webpack-cli.js index 60919f48ea9..4fe27326cbe 100644 --- a/packages/webpack-cli/lib/webpack-cli.js +++ b/packages/webpack-cli/lib/webpack-cli.js @@ -1,19 +1,65 @@ -const packageExists = require('./utils/package-exists'); +const path = require('path'); const webpack = packageExists('webpack') ? require('webpack') : undefined; -const logger = require('./utils/logger'); const webpackMerge = require('webpack-merge'); -const { core, coreFlagMap } = require('./utils/cli-flags'); +const { writeFileSync } = require('fs'); +const { options: coloretteOptions, yellow } = require('colorette'); + +const packageExists = require('./utils/package-exists'); +const logger = require('./utils/logger'); +const { core, groups, coreFlagMap } = require('./utils/cli-flags'); const argParser = require('./utils/arg-parser'); const assignFlagDefaults = require('./utils/flag-defaults'); -const { writeFileSync } = require('fs'); -const { options: coloretteOptions } = require('colorette'); const WebpackCLIPlugin = require('./plugins/WebpackCLIPlugin'); +const promptInstallation = require('./utils/prompt-installation'); // CLI arg resolvers const handleConfigResolution = require('./groups/resolveConfig'); -const basicResolver = require('./groups/basicResolver'); const toKebabCase = require('./utils/to-kebab-case'); +const WEBPACK_OPTION_FLAGS = core + .filter((coreFlag) => { + return coreFlag.group === groups.BASIC_GROUP; + }) + .reduce((result, flagObject) => { + result.push(flagObject.name); + if (flagObject.alias) { + result.push(flagObject.alias); + } + return result; + }, []); + +const PRODUCTION = 'production'; +const DEVELOPMENT = 'development'; + +/* + Mode priority: + - Mode flag + - Mode from config + - Mode form NODE_ENV + */ +/** + * + * @param {string} mode - mode flag value + * @param {Object} configObject - contains relevant loaded config + */ +const assignMode = (mode, configObject) => { + const { + env: { NODE_ENV }, + } = process; + const { mode: configMode } = configObject; + let finalMode; + if (mode) { + finalMode = mode; + } else if (configMode) { + finalMode = configMode; + } else if (NODE_ENV && (NODE_ENV === PRODUCTION || NODE_ENV === DEVELOPMENT)) { + finalMode = NODE_ENV; + } else { + finalMode = PRODUCTION; + } + return finalMode; +}; + class WebpackCLI { constructor() { this.compilerConfiguration = {}; @@ -44,6 +90,96 @@ class WebpackCLI { this._mergeOptionsToConfiguration(configWithDefaults); } + async resolveArgs(args, configOptions = {}) { + const { outputPath, stats, json, mode, target, prefetch, hot, analyze } = args; + + const finalOptions = { + options: {}, + outputOptions: {}, + }; + Object.keys(args).forEach((arg) => { + if (WEBPACK_OPTION_FLAGS.includes(arg)) { + finalOptions.outputOptions[arg] = args[arg]; + } + if (arg === 'devtool') { + finalOptions.options.devtool = args[arg]; + } + if (arg === 'name') { + finalOptions.options.name = args[arg]; + } + if (arg === 'watch') { + finalOptions.options.watch = true; + } + if (arg === 'entry') { + finalOptions.options[arg] = args[arg]; + } + }); + if (outputPath) { + finalOptions.options.output = { path: path.resolve(outputPath) }; + } + + if (stats !== undefined) { + finalOptions.options.stats = stats; + } + if (json) { + finalOptions.outputOptions.json = json; + } + + if (hot) { + const { HotModuleReplacementPlugin } = require('webpack'); + const hotModuleVal = new HotModuleReplacementPlugin(); + if (finalOptions.options && finalOptions.options.plugins) { + finalOptions.options.plugins.unshift(hotModuleVal); + } else { + finalOptions.options.plugins = [hotModuleVal]; + } + } + if (prefetch) { + const { PrefetchPlugin } = require('webpack'); + const prefetchVal = new PrefetchPlugin(null, args.prefetch); + if (finalOptions.options && finalOptions.options.plugins) { + finalOptions.options.plugins.unshift(prefetchVal); + } else { + finalOptions.options.plugins = [prefetchVal]; + } + } + if (analyze) { + if (packageExists('webpack-bundle-analyzer')) { + // eslint-disable-next-line node/no-extraneous-require + const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); + const bundleAnalyzerVal = new BundleAnalyzerPlugin(); + if (finalOptions.options && finalOptions.options.plugins) { + finalOptions.options.plugins.unshift(bundleAnalyzerVal); + } else { + finalOptions.options.plugins = [bundleAnalyzerVal]; + } + } else { + await promptInstallation('webpack-bundle-analyzer', () => { + logger.error(`It looks like ${yellow('webpack-bundle-analyzer')} is not installed.`); + }) + .then(() => logger.success(`${yellow('webpack-bundle-analyzer')} was installed sucessfully.`)) + .catch(() => { + logger.error(`Action Interrupted, Please try once again or install ${yellow('webpack-bundle-analyzer')} manually.`); + process.exit(2); + }); + } + } + if (target) { + finalOptions.options.target = args.target; + } + + if (Array.isArray(configOptions)) { + // Todo - handle multi config for all flags + finalOptions.options = configOptions.map(() => ({ ...finalOptions.options })); + configOptions.forEach((configObject, index) => { + finalOptions.options[index].mode = assignMode(mode, configObject); + }); + } else { + finalOptions.options.mode = assignMode(mode, configOptions); + } + return finalOptions; + } + async _baseResolver(cb, parsedArgs, strategy) { const resolvedConfig = await cb(parsedArgs, this.compilerConfiguration); this._mergeOptionsToConfiguration(resolvedConfig.options, strategy); @@ -143,7 +279,7 @@ class WebpackCLI { await Promise.resolve() .then(() => this._baseResolver(handleConfigResolution, parsedArgs)) .then(() => this._handleCoreFlags(parsedArgs)) - .then(() => this._baseResolver(basicResolver, parsedArgs)); + .then(() => this._baseResolver(this.resolveArgs, parsedArgs)); } handleError(error) {