From d630c10f3a661542bbfff623652355c932ebbc48 Mon Sep 17 00:00:00 2001 From: Damian Pieczynski Date: Thu, 22 Oct 2020 16:10:55 +0200 Subject: [PATCH 01/12] refactor: pass a callback to webpack from webpack-cli --- packages/webpack-cli/lib/webpack-cli.js | 150 +++++++++--------- test/analyze/analyze-flag.test.js | 8 +- .../invalid-export/invalid-export.test.js | 2 +- test/core-flags/cache-flags.test.js | 48 +++--- test/error/error.test.js | 2 +- test/invalid-schema/invalid-schema.test.js | 4 +- test/stats/cli-flags/stats.test.js | 2 +- test/utils/cli-plugin-test/plugin.test.js | 2 +- 8 files changed, 111 insertions(+), 107 deletions(-) diff --git a/packages/webpack-cli/lib/webpack-cli.js b/packages/webpack-cli/lib/webpack-cli.js index 07bdf950c40..a3881e117ec 100644 --- a/packages/webpack-cli/lib/webpack-cli.js +++ b/packages/webpack-cli/lib/webpack-cli.js @@ -212,25 +212,28 @@ class WebpackCLI extends GroupHelper { return this.runOptionGroups(args); } - createCompiler(options) { + handleError(error) { + // https://github.com/webpack/webpack/blob/master/lib/index.js#L267 + // https://github.com/webpack/webpack/blob/v4.44.2/lib/webpack.js#L90 + const ValidationError = webpack.ValidationError ? webpack.ValidationError : webpack.WebpackOptionsValidationError; + + // In case of schema errors print and exit process + // For webpack@4 and webpack@5 + if (error instanceof ValidationError) { + logger.error(error.message); + } else { + logger.error(error); + } + } + + createCompiler(options, callback) { let compiler; try { - compiler = webpack(options); + compiler = webpack(options, callback); } catch (error) { - // https://github.com/webpack/webpack/blob/master/lib/index.js#L267 - // https://github.com/webpack/webpack/blob/v4.44.2/lib/webpack.js#L90 - const ValidationError = webpack.ValidationError ? webpack.ValidationError : webpack.WebpackOptionsValidationError; - - // In case of schema errors print and exit process - // For webpack@4 and webpack@5 - if (error instanceof ValidationError) { - logger.error(error.message); - } else { - logger.error(error); - } - - process.exit(2); + this.handleError(error); + process.exit(1); } return compiler; @@ -245,53 +248,73 @@ class WebpackCLI extends GroupHelper { async run(args, cliOptions) { await this.processArgs(args, cliOptions); - const compiler = this.createCompiler(this.compilerConfiguration); - - const options = this.compilerConfiguration; - const outputOptions = this.outputConfiguration; + let options = this.compilerConfiguration; + let outputOptions = this.outputConfiguration; - if (outputOptions.interactive) { - const interactive = require('./utils/interactive'); + let isWatchMode = false; - return interactive(compiler, options, outputOptions); + if (Array.isArray(options)) { + isWatchMode = options.some((options) => options.watch); + } else { + isWatchMode = options.watch; } - const compilers = compiler.compilers ? compiler.compilers : [compiler]; - const isWatchMode = Boolean(compilers.find((compiler) => compiler.options.watch)); - const isRawOutput = typeof outputOptions.json === 'undefined'; + const PluginName = 'webpack-cli'; - if (isRawOutput) { - for (const compiler of compilers) { - if (outputOptions.progress) { - const { ProgressPlugin } = webpack; + class WebpackCLIPlugin { + async apply(compiler) { + const compilers = compiler.compilers ? compiler.compilers : [compiler]; - let progressPluginExists; + for (const compiler of compilers) { + if (outputOptions.progress) { + const { ProgressPlugin } = webpack; - if (compiler.options.plugins) { - progressPluginExists = Boolean(compiler.options.plugins.find((e) => e instanceof ProgressPlugin)); - } + let progressPluginExists; - if (!progressPluginExists) { - new ProgressPlugin().apply(compiler); + if (compiler.options.plugins) { + progressPluginExists = Boolean(compiler.options.plugins.find((e) => e instanceof ProgressPlugin)); + } + + if (!progressPluginExists) { + new ProgressPlugin().apply(compiler); + } } } + + compiler.hooks.watchRun.tap(PluginName, (compilation) => { + if (compilation.options.bail && isWatchMode) { + logger.warn('You are using "bail" with "watch". "bail" will still exit webpack when the first error is found.'); + } + + logger.success(`Compilation${compilation.name ? `${compilation.name}` : ''} starting...`); + }); + compiler.hooks.done.tap(PluginName, (compilation) => { + logger.success(`Compilation${compilation.name ? `${compilation.name}` : ''} finished`); + }); } + } - compiler.hooks.watchRun.tap('watchInfo', (compilation) => { - if (compilation.options.bail && isWatchMode) { - logger.warn('You are using "bail" with "watch". "bail" will still exit webpack when the first error is found.'); - } + const isRawOutput = typeof outputOptions.json === 'undefined'; - logger.success(`Compilation${compilation.name ? `${compilation.name}` : ''} starting...`); - }); - compiler.hooks.done.tap('watchInfo', (compilation) => { - logger.success(`Compilation${compilation.name ? `${compilation.name}` : ''} finished`); - }); + if (isRawOutput) { + const webpackCLIPlugin = new WebpackCLIPlugin(); + + const addPlugin = (options) => { + if (!options.plugins) { + options.plugins = []; + } + options.plugins.unshift(webpackCLIPlugin); + }; + if (Array.isArray(options)) { + options.forEach(addPlugin); + } else { + addPlugin(options); + } } const callback = (error, stats) => { if (error) { - logger.error(error); + this.handleError(error); process.exit(1); } @@ -341,40 +364,15 @@ class WebpackCLI extends GroupHelper { } }; - if (isWatchMode) { - const watchOptions = (compiler.options && compiler.options.watchOptions) || {}; + const compiler = this.createCompiler(options, callback); - if (watchOptions.stdin) { - process.stdin.on('end', function () { - process.exit(); - }); - process.stdin.resume(); - } - - return new Promise((resolve) => { - compiler.watch(watchOptions, (error, stats) => { - callback(error, stats); + if (compiler && outputOptions.interactive) { + const interactive = require('./utils/interactive'); - resolve(); - }); - }); - } else { - return new Promise((resolve) => { - compiler.run((error, stats) => { - if (compiler.close) { - compiler.close(() => { - callback(error, stats); - - resolve(); - }); - } else { - callback(error, stats); - - resolve(); - } - }); - }); + interactive(compiler, options, outputOptions); } + + return Promise.resolve(); } } diff --git a/test/analyze/analyze-flag.test.js b/test/analyze/analyze-flag.test.js index ec27d3b78ac..0b83fecb6ad 100644 --- a/test/analyze/analyze-flag.test.js +++ b/test/analyze/analyze-flag.test.js @@ -8,13 +8,15 @@ describe('--analyze flag', () => { proc.stdout.on('data', (chunk) => { const data = chunk.toString(); + // console.log(data) if (data.includes('Webpack Bundle Analyzer is started at')) { expect(data).toContain('Webpack Bundle Analyzer is started at'); - - proc.kill(); - done(); } + // FIXME + + proc.kill(); + done(); }); }); }); diff --git a/test/config/invalid-export/invalid-export.test.js b/test/config/invalid-export/invalid-export.test.js index ca1abec6ab5..8619c3e1f52 100644 --- a/test/config/invalid-export/invalid-export.test.js +++ b/test/config/invalid-export/invalid-export.test.js @@ -9,6 +9,6 @@ describe('invalid export', () => { expect(stderr).toBeTruthy(); expect(stderr).toContain('Invalid configuration object'); - expect(exitCode).toBe(2); + expect(exitCode).toBe(1); }); }); diff --git a/test/core-flags/cache-flags.test.js b/test/core-flags/cache-flags.test.js index 8a2cb8ccbb8..0c7524b2858 100644 --- a/test/core-flags/cache-flags.test.js +++ b/test/core-flags/cache-flags.test.js @@ -1,7 +1,11 @@ 'use strict'; const { run, isWindows } = require('../utils/test-utils'); -const { existsSync, writeFileSync, unlinkSync } = require('fs'); +const { + existsSync, + // writeFileSync, + // unlinkSync +} = require('fs'); const { resolve } = require('path'); describe('cache related flags from core', () => { @@ -121,25 +125,25 @@ describe('cache related flags from core', () => { expect(exitCode).toEqual(0); }); - it('should invalidate cache when config changes', () => { - // TODO: Fix on windows - if (isWindows) return; - // Creating a temporary webpack config - writeFileSync(resolve(__dirname, './webpack.test.config.js'), 'module.exports = {mode: "development"}'); - const { stderr, stdout } = run(__dirname, ['--cache-type', 'filesystem', '-c', './webpack.test.config.js']); - expect(stderr).toBeFalsy(); - expect(stdout).not.toContain('[cached]'); - - // Running again should use the cache - const newRun = run(__dirname, ['--cache-type', 'filesystem', '-c', './webpack.test.config.js']); - expect(newRun.stdout).toContain('[cached]'); - - // Change config to invalidate cache - writeFileSync(resolve(__dirname, './webpack.test.config.js'), 'module.exports = {mode: "production"}'); - - const newRun2 = run(__dirname, ['--cache-type', 'filesystem', '-c', './webpack.test.config.js']); - unlinkSync(resolve(__dirname, './webpack.test.config.js')); - expect(newRun2).not.toContain('[cached]'); - expect(newRun2.exitCode).toEqual(0); - }); + // it('should invalidate cache when config changes', () => { + // // TODO: Fix on windows + // if (isWindows) return; + // // Creating a temporary webpack config + // writeFileSync(resolve(__dirname, './webpack.test.config.js'), 'module.exports = {mode: "development"}'); + // const { stderr, stdout } = run(__dirname, ['--cache-type', 'filesystem', '-c', './webpack.test.config.js']); + // expect(stderr).toBeFalsy(); + // expect(stdout).not.toContain('[cached]'); + + // // Running again should use the cache + // const newRun = run(__dirname, ['--cache-type', 'filesystem', '-c', './webpack.test.config.js']); + // expect(newRun.stdout).toContain('[cached]'); + + // // Change config to invalidate cache + // writeFileSync(resolve(__dirname, './webpack.test.config.js'), 'module.exports = {mode: "production"}'); + + // const newRun2 = run(__dirname, ['--cache-type', 'filesystem', '-c', './webpack.test.config.js']); + // unlinkSync(resolve(__dirname, './webpack.test.config.js')); + // expect(newRun2).not.toContain('[cached]'); + // expect(newRun2.exitCode).toEqual(0); + // }); }); diff --git a/test/error/error.test.js b/test/error/error.test.js index de30128d161..46d25d4213e 100644 --- a/test/error/error.test.js +++ b/test/error/error.test.js @@ -9,6 +9,6 @@ describe('error', () => { expect(stderr).toContain('Error: test'); expect(stderr).toMatch(/at .+ (.+)/); expect(stdout).toBeFalsy(); - expect(exitCode).toBe(2); + expect(exitCode).toBe(1); }); }); diff --git a/test/invalid-schema/invalid-schema.test.js b/test/invalid-schema/invalid-schema.test.js index c107f966f9e..21af9faddcb 100644 --- a/test/invalid-schema/invalid-schema.test.js +++ b/test/invalid-schema/invalid-schema.test.js @@ -6,7 +6,7 @@ describe('invalid schema', () => { const { stderr, exitCode } = run(__dirname, ['--config', './webpack.config.mock.js']); expect(stderr).toContain('Invalid configuration object'); if (!isWindows) { - expect(exitCode).toEqual(2); + expect(exitCode).toEqual(1); } }); @@ -14,7 +14,7 @@ describe('invalid schema', () => { const { stderr, exitCode } = run(__dirname, ['--mode', 'Yukihira']); expect(stderr).toContain('Invalid configuration object'); if (!isWindows) { - expect(exitCode).toEqual(2); + expect(exitCode).toEqual(1); } }); }); diff --git a/test/stats/cli-flags/stats.test.js b/test/stats/cli-flags/stats.test.js index e8baa9b0f20..a02b74bae95 100644 --- a/test/stats/cli-flags/stats.test.js +++ b/test/stats/cli-flags/stats.test.js @@ -45,7 +45,7 @@ describe('stats flag', () => { } // TODO - Fix exitcode check on windows if (!isWindows) { - expect(exitCode).toEqual(2); + expect(exitCode).toEqual(1); } }); }); diff --git a/test/utils/cli-plugin-test/plugin.test.js b/test/utils/cli-plugin-test/plugin.test.js index 96a5ff20c27..14e4810a3fa 100644 --- a/test/utils/cli-plugin-test/plugin.test.js +++ b/test/utils/cli-plugin-test/plugin.test.js @@ -10,6 +10,6 @@ describe('webpack-cli-test-plugin Test', () => { if (typeof cli !== 'undefined') { expect(stdout).toContain(`alias: { alias: [ 'alias1', 'alias2' ] }`); } - expect(stdout).toContain('plugins: [ WebpackCLITestPlugin { opts: [Array], showAll: true } ]'); + expect(stdout).toContain(` WebpackCLITestPlugin { opts: [Array], showAll: true }`); }); }); From 34aebe6db63d25d19d646f7edfb0d32f800cb21b Mon Sep 17 00:00:00 2001 From: Damian Pieczynski Date: Thu, 22 Oct 2020 21:00:46 +0200 Subject: [PATCH 02/12] refactor: extract WebpackCLIPlugin --- .../lib/plugins/WebpackCLIPlugin.js | 44 ++++++++++++++ packages/webpack-cli/lib/webpack-cli.js | 59 +++++-------------- 2 files changed, 58 insertions(+), 45 deletions(-) create mode 100644 packages/webpack-cli/lib/plugins/WebpackCLIPlugin.js diff --git a/packages/webpack-cli/lib/plugins/WebpackCLIPlugin.js b/packages/webpack-cli/lib/plugins/WebpackCLIPlugin.js new file mode 100644 index 00000000000..5fc1032cee4 --- /dev/null +++ b/packages/webpack-cli/lib/plugins/WebpackCLIPlugin.js @@ -0,0 +1,44 @@ +const { packageExists } = require('../utils/package-exists'); +const webpack = packageExists('webpack') ? require('webpack') : undefined; +const logger = require('../utils/logger'); + +const PluginName = 'webpack-cli'; + +class WebpackCLIPlugin { + constructor(options) { + this.options = options; + } + async apply(compiler) { + const compilers = compiler.compilers ? compiler.compilers : [compiler]; + + for (const compiler of compilers) { + if (this.options.progress) { + const { ProgressPlugin } = webpack; + + let progressPluginExists; + + if (compiler.options.plugins) { + progressPluginExists = Boolean(compiler.options.plugins.find((e) => e instanceof ProgressPlugin)); + } + + if (!progressPluginExists) { + new ProgressPlugin().apply(compiler); + } + } + } + + compiler.hooks.watchRun.tap(PluginName, (compilation) => { + const { bail, watch } = compilation.options; + if (bail && watch) { + logger.warn('You are using "bail" with "watch". "bail" will still exit webpack when the first error is found.'); + } + + logger.success(`Compilation${compilation.name ? `${compilation.name}` : ''} starting...`); + }); + compiler.hooks.done.tap(PluginName, (compilation) => { + logger.success(`Compilation${compilation.name ? `${compilation.name}` : ''} finished`); + }); + } +} + +module.exports = WebpackCLIPlugin; diff --git a/packages/webpack-cli/lib/webpack-cli.js b/packages/webpack-cli/lib/webpack-cli.js index a3881e117ec..836ddedbbf0 100644 --- a/packages/webpack-cli/lib/webpack-cli.js +++ b/packages/webpack-cli/lib/webpack-cli.js @@ -10,6 +10,7 @@ const { toKebabCase } = require('./utils/helpers'); const assignFlagDefaults = require('./utils/flag-defaults'); const { writeFileSync } = require('fs'); const { options: coloretteOptions } = require('colorette'); +const WebpackCLIPlugin = require('./plugins/WebpackCLIPlugin'); // CLI arg resolvers const handleConfigResolution = require('./groups/ConfigGroup'); @@ -248,56 +249,16 @@ class WebpackCLI extends GroupHelper { async run(args, cliOptions) { await this.processArgs(args, cliOptions); + let compiler; let options = this.compilerConfiguration; let outputOptions = this.outputConfiguration; - let isWatchMode = false; - - if (Array.isArray(options)) { - isWatchMode = options.some((options) => options.watch); - } else { - isWatchMode = options.watch; - } - - const PluginName = 'webpack-cli'; - - class WebpackCLIPlugin { - async apply(compiler) { - const compilers = compiler.compilers ? compiler.compilers : [compiler]; - - for (const compiler of compilers) { - if (outputOptions.progress) { - const { ProgressPlugin } = webpack; - - let progressPluginExists; - - if (compiler.options.plugins) { - progressPluginExists = Boolean(compiler.options.plugins.find((e) => e instanceof ProgressPlugin)); - } - - if (!progressPluginExists) { - new ProgressPlugin().apply(compiler); - } - } - } - - compiler.hooks.watchRun.tap(PluginName, (compilation) => { - if (compilation.options.bail && isWatchMode) { - logger.warn('You are using "bail" with "watch". "bail" will still exit webpack when the first error is found.'); - } - - logger.success(`Compilation${compilation.name ? `${compilation.name}` : ''} starting...`); - }); - compiler.hooks.done.tap(PluginName, (compilation) => { - logger.success(`Compilation${compilation.name ? `${compilation.name}` : ''} finished`); - }); - } - } - const isRawOutput = typeof outputOptions.json === 'undefined'; if (isRawOutput) { - const webpackCLIPlugin = new WebpackCLIPlugin(); + const webpackCLIPlugin = new WebpackCLIPlugin({ + progress: outputOptions.progress, + }); const addPlugin = (options) => { if (!options.plugins) { @@ -359,12 +320,20 @@ class WebpackCLI extends GroupHelper { logger.raw(`${stats.toString(foundStats)}`); } + let isWatchMode = false; + + if (Array.isArray(options)) { + isWatchMode = options.some((options) => options.watch); + } else { + isWatchMode = options.watch; + } + if (isWatchMode) { logger.success('watching files for updates...'); } }; - const compiler = this.createCompiler(options, callback); + compiler = this.createCompiler(options, callback); if (compiler && outputOptions.interactive) { const interactive = require('./utils/interactive'); From 217475a1ac3ba4ab4d262c659a88b061020fd37a Mon Sep 17 00:00:00 2001 From: Damian Pieczynski Date: Thu, 22 Oct 2020 21:09:48 +0200 Subject: [PATCH 03/12] refactor: revert to error code 2 --- packages/webpack-cli/lib/webpack-cli.js | 4 ++-- test/config/invalid-export/invalid-export.test.js | 2 +- test/error/error.test.js | 2 +- test/invalid-schema/invalid-schema.test.js | 4 ++-- test/stats/cli-flags/stats.test.js | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/webpack-cli/lib/webpack-cli.js b/packages/webpack-cli/lib/webpack-cli.js index 836ddedbbf0..3fe654b7c2f 100644 --- a/packages/webpack-cli/lib/webpack-cli.js +++ b/packages/webpack-cli/lib/webpack-cli.js @@ -234,7 +234,7 @@ class WebpackCLI extends GroupHelper { compiler = webpack(options, callback); } catch (error) { this.handleError(error); - process.exit(1); + process.exit(2); } return compiler; @@ -276,7 +276,7 @@ class WebpackCLI extends GroupHelper { const callback = (error, stats) => { if (error) { this.handleError(error); - process.exit(1); + process.exit(2); } if (stats.hasErrors()) { diff --git a/test/config/invalid-export/invalid-export.test.js b/test/config/invalid-export/invalid-export.test.js index 8619c3e1f52..ca1abec6ab5 100644 --- a/test/config/invalid-export/invalid-export.test.js +++ b/test/config/invalid-export/invalid-export.test.js @@ -9,6 +9,6 @@ describe('invalid export', () => { expect(stderr).toBeTruthy(); expect(stderr).toContain('Invalid configuration object'); - expect(exitCode).toBe(1); + expect(exitCode).toBe(2); }); }); diff --git a/test/error/error.test.js b/test/error/error.test.js index 46d25d4213e..de30128d161 100644 --- a/test/error/error.test.js +++ b/test/error/error.test.js @@ -9,6 +9,6 @@ describe('error', () => { expect(stderr).toContain('Error: test'); expect(stderr).toMatch(/at .+ (.+)/); expect(stdout).toBeFalsy(); - expect(exitCode).toBe(1); + expect(exitCode).toBe(2); }); }); diff --git a/test/invalid-schema/invalid-schema.test.js b/test/invalid-schema/invalid-schema.test.js index 21af9faddcb..c107f966f9e 100644 --- a/test/invalid-schema/invalid-schema.test.js +++ b/test/invalid-schema/invalid-schema.test.js @@ -6,7 +6,7 @@ describe('invalid schema', () => { const { stderr, exitCode } = run(__dirname, ['--config', './webpack.config.mock.js']); expect(stderr).toContain('Invalid configuration object'); if (!isWindows) { - expect(exitCode).toEqual(1); + expect(exitCode).toEqual(2); } }); @@ -14,7 +14,7 @@ describe('invalid schema', () => { const { stderr, exitCode } = run(__dirname, ['--mode', 'Yukihira']); expect(stderr).toContain('Invalid configuration object'); if (!isWindows) { - expect(exitCode).toEqual(1); + expect(exitCode).toEqual(2); } }); }); diff --git a/test/stats/cli-flags/stats.test.js b/test/stats/cli-flags/stats.test.js index a02b74bae95..e8baa9b0f20 100644 --- a/test/stats/cli-flags/stats.test.js +++ b/test/stats/cli-flags/stats.test.js @@ -45,7 +45,7 @@ describe('stats flag', () => { } // TODO - Fix exitcode check on windows if (!isWindows) { - expect(exitCode).toEqual(1); + expect(exitCode).toEqual(2); } }); }); From e2100897285cd3d6b6c08f8fceb51d81a3a89af2 Mon Sep 17 00:00:00 2001 From: Damian Pieczynski Date: Thu, 22 Oct 2020 21:12:54 +0200 Subject: [PATCH 04/12] fix: uncomment cache-flags.test --- test/core-flags/cache-flags.test.js | 48 +++++++++++++---------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/test/core-flags/cache-flags.test.js b/test/core-flags/cache-flags.test.js index 0c7524b2858..8a2cb8ccbb8 100644 --- a/test/core-flags/cache-flags.test.js +++ b/test/core-flags/cache-flags.test.js @@ -1,11 +1,7 @@ 'use strict'; const { run, isWindows } = require('../utils/test-utils'); -const { - existsSync, - // writeFileSync, - // unlinkSync -} = require('fs'); +const { existsSync, writeFileSync, unlinkSync } = require('fs'); const { resolve } = require('path'); describe('cache related flags from core', () => { @@ -125,25 +121,25 @@ describe('cache related flags from core', () => { expect(exitCode).toEqual(0); }); - // it('should invalidate cache when config changes', () => { - // // TODO: Fix on windows - // if (isWindows) return; - // // Creating a temporary webpack config - // writeFileSync(resolve(__dirname, './webpack.test.config.js'), 'module.exports = {mode: "development"}'); - // const { stderr, stdout } = run(__dirname, ['--cache-type', 'filesystem', '-c', './webpack.test.config.js']); - // expect(stderr).toBeFalsy(); - // expect(stdout).not.toContain('[cached]'); - - // // Running again should use the cache - // const newRun = run(__dirname, ['--cache-type', 'filesystem', '-c', './webpack.test.config.js']); - // expect(newRun.stdout).toContain('[cached]'); - - // // Change config to invalidate cache - // writeFileSync(resolve(__dirname, './webpack.test.config.js'), 'module.exports = {mode: "production"}'); - - // const newRun2 = run(__dirname, ['--cache-type', 'filesystem', '-c', './webpack.test.config.js']); - // unlinkSync(resolve(__dirname, './webpack.test.config.js')); - // expect(newRun2).not.toContain('[cached]'); - // expect(newRun2.exitCode).toEqual(0); - // }); + it('should invalidate cache when config changes', () => { + // TODO: Fix on windows + if (isWindows) return; + // Creating a temporary webpack config + writeFileSync(resolve(__dirname, './webpack.test.config.js'), 'module.exports = {mode: "development"}'); + const { stderr, stdout } = run(__dirname, ['--cache-type', 'filesystem', '-c', './webpack.test.config.js']); + expect(stderr).toBeFalsy(); + expect(stdout).not.toContain('[cached]'); + + // Running again should use the cache + const newRun = run(__dirname, ['--cache-type', 'filesystem', '-c', './webpack.test.config.js']); + expect(newRun.stdout).toContain('[cached]'); + + // Change config to invalidate cache + writeFileSync(resolve(__dirname, './webpack.test.config.js'), 'module.exports = {mode: "production"}'); + + const newRun2 = run(__dirname, ['--cache-type', 'filesystem', '-c', './webpack.test.config.js']); + unlinkSync(resolve(__dirname, './webpack.test.config.js')); + expect(newRun2).not.toContain('[cached]'); + expect(newRun2.exitCode).toEqual(0); + }); }); From 996e388508480c30356c820b85295b1bbe08db4a Mon Sep 17 00:00:00 2001 From: Damian Pieczynski Date: Thu, 22 Oct 2020 21:26:12 +0200 Subject: [PATCH 05/12] refactor: set isWatchMode only once per run --- packages/webpack-cli/lib/webpack-cli.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/webpack-cli/lib/webpack-cli.js b/packages/webpack-cli/lib/webpack-cli.js index 3fe654b7c2f..bfc5dfd6e7f 100644 --- a/packages/webpack-cli/lib/webpack-cli.js +++ b/packages/webpack-cli/lib/webpack-cli.js @@ -253,6 +253,14 @@ class WebpackCLI extends GroupHelper { let options = this.compilerConfiguration; let outputOptions = this.outputConfiguration; + let isWatchMode; + + if (Array.isArray(options)) { + isWatchMode = options.some((options) => options.watch); + } else { + isWatchMode = options.watch; + } + const isRawOutput = typeof outputOptions.json === 'undefined'; if (isRawOutput) { @@ -320,14 +328,6 @@ class WebpackCLI extends GroupHelper { logger.raw(`${stats.toString(foundStats)}`); } - let isWatchMode = false; - - if (Array.isArray(options)) { - isWatchMode = options.some((options) => options.watch); - } else { - isWatchMode = options.watch; - } - if (isWatchMode) { logger.success('watching files for updates...'); } From fd846e20d1b6c287570db2ce206d3756863ebc42 Mon Sep 17 00:00:00 2001 From: Damian Pieczynski Date: Thu, 22 Oct 2020 21:46:53 +0200 Subject: [PATCH 06/12] fix: read ProgressPlugin from compiler.webpack for v5 --- packages/webpack-cli/lib/plugins/WebpackCLIPlugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webpack-cli/lib/plugins/WebpackCLIPlugin.js b/packages/webpack-cli/lib/plugins/WebpackCLIPlugin.js index 5fc1032cee4..268ff2ea68f 100644 --- a/packages/webpack-cli/lib/plugins/WebpackCLIPlugin.js +++ b/packages/webpack-cli/lib/plugins/WebpackCLIPlugin.js @@ -13,7 +13,7 @@ class WebpackCLIPlugin { for (const compiler of compilers) { if (this.options.progress) { - const { ProgressPlugin } = webpack; + const { ProgressPlugin } = compiler.webpack || webpack; let progressPluginExists; From 793b44416817484530ed121fe3cb680a3f973f06 Mon Sep 17 00:00:00 2001 From: Damian Pieczynski Date: Thu, 22 Oct 2020 22:44:50 +0200 Subject: [PATCH 07/12] refactor: move watching message to WebpackCLIPlugin --- .../webpack-cli/lib/plugins/WebpackCLIPlugin.js | 7 +++++++ packages/webpack-cli/lib/webpack-cli.js | 13 +------------ 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/packages/webpack-cli/lib/plugins/WebpackCLIPlugin.js b/packages/webpack-cli/lib/plugins/WebpackCLIPlugin.js index 268ff2ea68f..349736c09cf 100644 --- a/packages/webpack-cli/lib/plugins/WebpackCLIPlugin.js +++ b/packages/webpack-cli/lib/plugins/WebpackCLIPlugin.js @@ -35,8 +35,15 @@ class WebpackCLIPlugin { logger.success(`Compilation${compilation.name ? `${compilation.name}` : ''} starting...`); }); + compiler.hooks.done.tap(PluginName, (compilation) => { logger.success(`Compilation${compilation.name ? `${compilation.name}` : ''} finished`); + + process.nextTick(() => { + if (compiler.watchMode) { + logger.success('watching files for updates...'); + } + }); }); } } diff --git a/packages/webpack-cli/lib/webpack-cli.js b/packages/webpack-cli/lib/webpack-cli.js index bfc5dfd6e7f..e2b329d50b1 100644 --- a/packages/webpack-cli/lib/webpack-cli.js +++ b/packages/webpack-cli/lib/webpack-cli.js @@ -250,17 +250,10 @@ class WebpackCLI extends GroupHelper { await this.processArgs(args, cliOptions); let compiler; + let options = this.compilerConfiguration; let outputOptions = this.outputConfiguration; - let isWatchMode; - - if (Array.isArray(options)) { - isWatchMode = options.some((options) => options.watch); - } else { - isWatchMode = options.watch; - } - const isRawOutput = typeof outputOptions.json === 'undefined'; if (isRawOutput) { @@ -327,10 +320,6 @@ class WebpackCLI extends GroupHelper { } else { logger.raw(`${stats.toString(foundStats)}`); } - - if (isWatchMode) { - logger.success('watching files for updates...'); - } }; compiler = this.createCompiler(options, callback); From 65107dae56a6081abf0329bd429fadb9b76b5d10 Mon Sep 17 00:00:00 2001 From: Damian Pieczynski Date: Thu, 22 Oct 2020 23:43:32 +0200 Subject: [PATCH 08/12] fix: clear cache before each test in cache-flags.test.js --- test/core-flags/cache-flags.test.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/core-flags/cache-flags.test.js b/test/core-flags/cache-flags.test.js index 8a2cb8ccbb8..074e26b4790 100644 --- a/test/core-flags/cache-flags.test.js +++ b/test/core-flags/cache-flags.test.js @@ -1,10 +1,20 @@ 'use strict'; +const path = require('path'); +const rimraf = require('rimraf'); const { run, isWindows } = require('../utils/test-utils'); const { existsSync, writeFileSync, unlinkSync } = require('fs'); const { resolve } = require('path'); describe('cache related flags from core', () => { + beforeEach((done) => { + if (isWindows) return; + + rimraf(path.join(__dirname, '../../node_modules/.cache/webpack/*'), () => { + done(); + }); + }); + it('should be successful with --cache ', () => { const { stderr, stdout } = run(__dirname, ['--cache']); expect(stderr).toBeFalsy(); From 963e1e756982d2b44e265e78092a1df990ccde3f Mon Sep 17 00:00:00 2001 From: Damian Pieczynski Date: Fri, 23 Oct 2020 09:08:03 +0200 Subject: [PATCH 09/12] fix: compiler.options can be undefined in webpack 4 --- packages/webpack-cli/lib/webpack-cli.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/webpack-cli/lib/webpack-cli.js b/packages/webpack-cli/lib/webpack-cli.js index e2b329d50b1..9afb777a51b 100644 --- a/packages/webpack-cli/lib/webpack-cli.js +++ b/packages/webpack-cli/lib/webpack-cli.js @@ -299,9 +299,11 @@ class WebpackCLI extends GroupHelper { return stats; }; + const getStatsOptionsFromCompiler = (compiler) => getStatsOptions(compiler.options ? compiler.options.stats : undefined); + const foundStats = compiler.compilers - ? { children: compiler.compilers.map((compiler) => getStatsOptions(compiler.options.stats)) } - : getStatsOptions(compiler.options.stats); + ? { children: compiler.compilers.map(getStatsOptionsFromCompiler) } + : getStatsOptionsFromCompiler(compiler); if (outputOptions.json === true) { process.stdout.write(JSON.stringify(stats.toJson(foundStats), null, 2) + '\n'); From f2cc6152cde2510b2b36fec1dbc64d67e79882af Mon Sep 17 00:00:00 2001 From: Damian Pieczynski Date: Fri, 23 Oct 2020 14:24:24 +0200 Subject: [PATCH 10/12] fix: revert analyze flag test --- test/analyze/analyze-flag.test.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/test/analyze/analyze-flag.test.js b/test/analyze/analyze-flag.test.js index 0b83fecb6ad..eb0fa030fa2 100644 --- a/test/analyze/analyze-flag.test.js +++ b/test/analyze/analyze-flag.test.js @@ -8,15 +8,12 @@ describe('--analyze flag', () => { proc.stdout.on('data', (chunk) => { const data = chunk.toString(); - // console.log(data) if (data.includes('Webpack Bundle Analyzer is started at')) { expect(data).toContain('Webpack Bundle Analyzer is started at'); + proc.kill(); + done(); } - // FIXME - - proc.kill(); - done(); }); }); }); From 928a811aace9e5d7ff88d3421274d09d35a265cf Mon Sep 17 00:00:00 2001 From: Damian Pieczynski Date: Fri, 23 Oct 2020 17:50:18 +0200 Subject: [PATCH 11/12] fix: tests --- test/analyze/analyze-flag.test.js | 1 + test/core-flags/cache-flags.test.js | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/test/analyze/analyze-flag.test.js b/test/analyze/analyze-flag.test.js index eb0fa030fa2..ec27d3b78ac 100644 --- a/test/analyze/analyze-flag.test.js +++ b/test/analyze/analyze-flag.test.js @@ -11,6 +11,7 @@ describe('--analyze flag', () => { if (data.includes('Webpack Bundle Analyzer is started at')) { expect(data).toContain('Webpack Bundle Analyzer is started at'); + proc.kill(); done(); } diff --git a/test/core-flags/cache-flags.test.js b/test/core-flags/cache-flags.test.js index 074e26b4790..57a1f0338ac 100644 --- a/test/core-flags/cache-flags.test.js +++ b/test/core-flags/cache-flags.test.js @@ -8,8 +8,6 @@ const { resolve } = require('path'); describe('cache related flags from core', () => { beforeEach((done) => { - if (isWindows) return; - rimraf(path.join(__dirname, '../../node_modules/.cache/webpack/*'), () => { done(); }); From 40b202ffbe78ee3b2dbec4aff741968fb59e43cc Mon Sep 17 00:00:00 2001 From: Damian Pieczynski Date: Sun, 25 Oct 2020 10:57:32 +0100 Subject: [PATCH 12/12] refactor: replace ternary with or operator where applicable --- packages/webpack-cli/lib/plugins/WebpackCLIPlugin.js | 8 +++++--- packages/webpack-cli/lib/webpack-cli.js | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/webpack-cli/lib/plugins/WebpackCLIPlugin.js b/packages/webpack-cli/lib/plugins/WebpackCLIPlugin.js index 349736c09cf..c79c8654a95 100644 --- a/packages/webpack-cli/lib/plugins/WebpackCLIPlugin.js +++ b/packages/webpack-cli/lib/plugins/WebpackCLIPlugin.js @@ -9,7 +9,7 @@ class WebpackCLIPlugin { this.options = options; } async apply(compiler) { - const compilers = compiler.compilers ? compiler.compilers : [compiler]; + const compilers = compiler.compilers || [compiler]; for (const compiler of compilers) { if (this.options.progress) { @@ -27,17 +27,19 @@ class WebpackCLIPlugin { } } + const compilationName = (compilation) => (compilation.name ? ` ${compilation.name}` : ''); + compiler.hooks.watchRun.tap(PluginName, (compilation) => { const { bail, watch } = compilation.options; if (bail && watch) { logger.warn('You are using "bail" with "watch". "bail" will still exit webpack when the first error is found.'); } - logger.success(`Compilation${compilation.name ? `${compilation.name}` : ''} starting...`); + logger.success(`Compilation${compilationName(compilation)} starting...`); }); compiler.hooks.done.tap(PluginName, (compilation) => { - logger.success(`Compilation${compilation.name ? `${compilation.name}` : ''} finished`); + logger.success(`Compilation${compilationName(compilation)} finished`); process.nextTick(() => { if (compiler.watchMode) { diff --git a/packages/webpack-cli/lib/webpack-cli.js b/packages/webpack-cli/lib/webpack-cli.js index 9afb777a51b..9ae5c1ae010 100644 --- a/packages/webpack-cli/lib/webpack-cli.js +++ b/packages/webpack-cli/lib/webpack-cli.js @@ -216,7 +216,7 @@ class WebpackCLI extends GroupHelper { handleError(error) { // https://github.com/webpack/webpack/blob/master/lib/index.js#L267 // https://github.com/webpack/webpack/blob/v4.44.2/lib/webpack.js#L90 - const ValidationError = webpack.ValidationError ? webpack.ValidationError : webpack.WebpackOptionsValidationError; + const ValidationError = webpack.ValidationError || webpack.WebpackOptionsValidationError; // In case of schema errors print and exit process // For webpack@4 and webpack@5