diff --git a/README.md b/README.md index 89451a21e..a403ea19e 100644 --- a/README.md +++ b/README.md @@ -96,11 +96,18 @@ Please see the documentation for [`mime-types`](https://github.com/jshttp/mime-t ### publicPath Type: `String` -Default: `output.publicPath` +Default: `output.publicPath` (from a configuration) The public path that the middleware is bound to. -_Best Practice: use the same `publicPath` defined in your webpack config. -For more information about `publicPath`, please see [the webpack documentation](https://webpack.js.org/guides/public-path)._ + +_Best Practice: use the same `publicPath` defined in your webpack config. For more information about `publicPath`, please see [the webpack documentation](https://webpack.js.org/guides/public-path)._ + +### stats + +Type: `Boolean|String|Object` +Default: `stats` (from a configuration) + +Stats options object or preset name. ### serverSideRender diff --git a/src/options.json b/src/options.json index f5d9a0baf..0969a0154 100644 --- a/src/options.json +++ b/src/options.json @@ -41,6 +41,30 @@ } ] }, + "stats": { + "description": "Stats options object or preset name.", + "anyOf": [ + { + "enum": [ + "none", + "summary", + "errors-only", + "errors-warnings", + "minimal", + "normal", + "detailed", + "verbose" + ] + }, + { + "type": "boolean" + }, + { + "type": "object", + "additionalProperties": true + } + ] + }, "serverSideRender": { "description": "Instructs the module to enable or disable the server-side rendering mode.", "type": "boolean" diff --git a/src/utils/setupHooks.js b/src/utils/setupHooks.js index 1e62510c2..42ca21d0a 100644 --- a/src/utils/setupHooks.js +++ b/src/utils/setupHooks.js @@ -28,6 +28,19 @@ export default function setupHooks(context) { // eslint-disable-next-line no-param-reassign statsOptions = webpack.Stats.presetToOptions(statsOptions); } + + return statsOptions; + } + + if (typeof statsOptions === 'undefined') { + // eslint-disable-next-line no-param-reassign + statsOptions = { preset: 'normal' }; + } else if (typeof statsOptions === 'boolean') { + // eslint-disable-next-line no-param-reassign + statsOptions = statsOptions ? { preset: 'normal' } : { preset: 'none' }; + } else if (typeof statsOptions === 'string') { + // eslint-disable-next-line no-param-reassign + statsOptions = { preset: statsOptions }; } return statsOptions; @@ -42,7 +55,7 @@ export default function setupHooks(context) { // Do the stuff in nextTick, because bundle may be invalidated if a change happened while compiling process.nextTick(() => { - const { compiler, logger, state, callbacks } = context; + const { compiler, logger, options, state, callbacks } = context; // Check if still in valid state if (!state) { @@ -51,11 +64,21 @@ export default function setupHooks(context) { logger.log('Compilation finished'); - let statsOptions = compiler.compilers - ? { children: compiler.compilers.map((child) => child.options.stats) } - : compiler.options.stats; + const isMultiCompilerMode = Boolean(compiler.compilers); + + let statsOptions; + + if (typeof options.stats !== 'undefined') { + statsOptions = isMultiCompilerMode + ? { children: compiler.compilers.map(() => options.stats) } + : options.stats; + } else { + statsOptions = isMultiCompilerMode + ? { children: compiler.compilers.map((child) => child.options.stats) } + : compiler.options.stats; + } - if (compiler.compilers) { + if (isMultiCompilerMode) { statsOptions.children = statsOptions.children.map( (childStatsOptions) => { // eslint-disable-next-line no-param-reassign diff --git a/test/__snapshots__/logging.test.js.snap.webpack4 b/test/__snapshots__/logging.test.js.snap.webpack4 index d1a8e3c51..3a5080383 100644 --- a/test/__snapshots__/logging.test.js.snap.webpack4 +++ b/test/__snapshots__/logging.test.js.snap.webpack4 @@ -208,6 +208,23 @@ Entrypoint main = bundle.js [./svg.svg] x bytes {main} [built]" `; +exports[`logging should logging on successfully build and respect the "NO_COLOR" env: stderr 1`] = `""`; + +exports[`logging should logging on successfully build and respect the "NO_COLOR" env: stdout 1`] = ` +"Hash: xxxx +Version: webpack x.x.x +Time: Xms +Built at: x +Asset Size Chunks Chunk Names +bundle.js x KiB main [emitted] main +index.html x bytes [emitted] +svg.svg x KiB [emitted] +Entrypoint main = bundle.js +[./foo.js] x bytes {main} [built] +[./index.html] x bytes {main} [built] +[./svg.svg] x bytes {main} [built]" +`; + exports[`logging should logging on successfully build and respect the "stats" option from configuration with custom object value: stderr 1`] = `""`; exports[`logging should logging on successfully build and respect the "stats" option from configuration with custom object value: stdout 1`] = ` @@ -299,6 +316,101 @@ Entrypoint main = bundle.js [./bar.js] x bytes {main} [built]" `; +exports[`logging should logging on successfully build using the "stats" option for middleware with object value and no colors: stderr 1`] = `""`; + +exports[`logging should logging on successfully build using the "stats" option for middleware with object value and no colors: stdout 1`] = ` +"Asset Size Chunks Chunk Names +bundle.js x KiB main [emitted] main +index.html x bytes [emitted] +svg.svg x KiB [emitted]" +`; + +exports[`logging should logging on successfully build using the "stats" option for middleware with object value: stderr 1`] = `""`; + +exports[`logging should logging on successfully build using the "stats" option for middleware with object value: stdout 1`] = ` +"Asset Size Chunks Chunk Names +bundle.js x KiB main [emitted] main +index.html x bytes [emitted] +svg.svg x KiB [emitted]" +`; + +exports[`logging should logging on successfully build using the "stats" option for middleware with the "false" value: stderr 1`] = `""`; + +exports[`logging should logging on successfully build using the "stats" option for middleware with the "false" value: stdout 1`] = `""`; + +exports[`logging should logging on successfully build using the "stats" option for middleware with the "none" value: stderr 1`] = `""`; + +exports[`logging should logging on successfully build using the "stats" option for middleware with the "none" value: stdout 1`] = `""`; + +exports[`logging should logging on successfully build using the "stats" option for middleware with the "normal" value: stderr 1`] = `""`; + +exports[`logging should logging on successfully build using the "stats" option for middleware with the "normal" value: stdout 1`] = ` +"Hash: xxxx +Version: webpack x.x.x +Time: Xms +Built at: x +Asset Size Chunks Chunk Names +bundle.js x KiB main [emitted] main +index.html x bytes [emitted] +svg.svg x KiB [emitted] +Entrypoint main = bundle.js +[./foo.js] x bytes {main} [built] +[./index.html] x bytes {main} [built] +[./svg.svg] x bytes {main} [built]" +`; + +exports[`logging should logging on successfully build using the "stats" option for middleware with the "true" value: stderr 1`] = `""`; + +exports[`logging should logging on successfully build using the "stats" option for middleware with the "true" value: stdout 1`] = ` +"Hash: xxxx +Version: webpack x.x.x +Time: Xms +Built at: x +Asset Size Chunks Chunk Names +bundle.js x KiB main [emitted] main +index.html x bytes [emitted] +svg.svg x KiB [emitted] +Entrypoint main = bundle.js +[./foo.js] x bytes {main} [built] +[./index.html] x bytes {main} [built] +[./svg.svg] x bytes {main} [built]" +`; + +exports[`logging should logging on successfully build using the "stats" option for middleware with the "verbose" value: stderr 1`] = `""`; + +exports[`logging should logging on successfully build using the "stats" option for middleware with the "verbose" value: stdout 1`] = ` +"Hash: xxxx +Version: webpack x.x.x +Time: Xms +Built at: x +Asset Size Chunks Chunk Names +bundle.js x KiB main [emitted] main +index.html x bytes [emitted] +svg.svg x KiB [emitted] +Entrypoint main = bundle.js +chunk {main} bundle.js (xxxx) x bytes [entry] [rendered] +> ./foo.js main +[./foo.js] x bytes {main} [depth 0] [built] +single entry ./foo.js main +[./index.html] x bytes {main} [depth 1] [built] +[exports: default] +cjs require ./index.html [./foo.js] 4:0-23 +[./svg.svg] x bytes {main} [depth 1] [built] +[exports: default] +cjs require ./svg.svg [./foo.js] 3:0-20 + +LOG from xxx" +`; + +exports[`logging should logging on successfully build using the "stats" option for middleware with the object value and colors: stderr 1`] = `""`; + +exports[`logging should logging on successfully build using the "stats" option for middleware with the object value and colors: stdout 1`] = ` +"Asset Size Chunks Chunk Names +bundle.js x KiB main [emitted] main +index.html x bytes [emitted] +svg.svg x KiB [emitted]" +`; + exports[`logging should logging on successfully build when the 'stats' doesn't exist: stderr 1`] = `""`; exports[`logging should logging on successfully build when the 'stats' doesn't exist: stdout 1`] = ` @@ -333,6 +445,103 @@ Entrypoint main = bundle.js [./svg.svg] x bytes {main} [built]" `; +exports[`logging should logging on successfully multi compiler build using the "stats" option for middleware with object value and colors: stderr 1`] = `""`; + +exports[`logging should logging on successfully multi compiler build using the "stats" option for middleware with object value and colors: stdout 1`] = ` +"Child +Asset Size Chunks Chunk Names +bundle.js x KiB main [emitted] main +index.html x bytes [emitted] +svg.svg x KiB [emitted] +Child +Asset Size Chunks Chunk Names +bundle.js x KiB main [emitted] main" +`; + +exports[`logging should logging on successfully multi compiler build using the "stats" option for middleware with object value and no colors: stderr 1`] = `""`; + +exports[`logging should logging on successfully multi compiler build using the "stats" option for middleware with object value and no colors: stdout 1`] = ` +"Child +Asset Size Chunks Chunk Names +bundle.js x KiB main [emitted] main +index.html x bytes [emitted] +svg.svg x KiB [emitted] +Child +Asset Size Chunks Chunk Names +bundle.js x KiB main [emitted] main" +`; + +exports[`logging should logging on successfully multi compiler build using the "stats" option for middleware with the "false" value: stderr 1`] = `""`; + +exports[`logging should logging on successfully multi compiler build using the "stats" option for middleware with the "false" value: stdout 1`] = `""`; + +exports[`logging should logging on successfully multi compiler build using the "stats" option for middleware with the "normal" value: stderr 1`] = `""`; + +exports[`logging should logging on successfully multi compiler build using the "stats" option for middleware with the "normal" value: stdout 1`] = ` +"Hash: xxxx +Version: webpack x.x.x +Child +Hash: xxxx +Time: Xms +Built at: x +Asset Size Chunks Chunk Names +bundle.js x KiB main [emitted] main +index.html x bytes [emitted] +svg.svg x KiB [emitted] +Entrypoint main = bundle.js +[./foo.js] x bytes {main} [built] +[./index.html] x bytes {main} [built] +[./svg.svg] x bytes {main} [built] +Child +Hash: xxxx +Time: Xms +Built at: x +Asset Size Chunks Chunk Names +bundle.js x KiB main [emitted] main +Entrypoint main = bundle.js +[./bar.js] x bytes {main} [built]" +`; + +exports[`logging should logging on successfully multi compiler build using the "stats" option for middleware with the "true" value: stderr 1`] = `""`; + +exports[`logging should logging on successfully multi compiler build using the "stats" option for middleware with the "true" value: stdout 1`] = ` +"Hash: xxxx +Version: webpack x.x.x +Child +Hash: xxxx +Time: Xms +Built at: x +Asset Size Chunks Chunk Names +bundle.js x KiB main [emitted] main +index.html x bytes [emitted] +svg.svg x KiB [emitted] +Entrypoint main = bundle.js +[./foo.js] x bytes {main} [built] +[./index.html] x bytes {main} [built] +[./svg.svg] x bytes {main} [built] +Child +Hash: xxxx +Time: Xms +Built at: x +Asset Size Chunks Chunk Names +bundle.js x KiB main [emitted] main +Entrypoint main = bundle.js +[./bar.js] x bytes {main} [built]" +`; + +exports[`logging should logging on successfully multi compiler build using the "stats" option for middleware with the object value: stderr 1`] = `""`; + +exports[`logging should logging on successfully multi compiler build using the "stats" option for middleware with the object value: stdout 1`] = ` +"Child +Asset Size Chunks Chunk Names +bundle.js x KiB main [emitted] main +index.html x bytes [emitted] +svg.svg x KiB [emitted] +Child +Asset Size Chunks Chunk Names +bundle.js x KiB main [emitted] main" +`; + exports[`logging should logging on unsuccessful build in multi-compiler: stderr 1`] = `""`; exports[`logging should logging on unsuccessful build in multi-compiler: stdout 1`] = ` diff --git a/test/__snapshots__/logging.test.js.snap.webpack5 b/test/__snapshots__/logging.test.js.snap.webpack5 index ccefdca87..2648a77f0 100644 --- a/test/__snapshots__/logging.test.js.snap.webpack5 +++ b/test/__snapshots__/logging.test.js.snap.webpack5 @@ -163,6 +163,20 @@ cacheable modules x bytes webpack x.x.x compiled successfully in x ms" `; +exports[`logging should logging on successfully build and respect the "NO_COLOR" env: stderr 1`] = `""`; + +exports[`logging should logging on successfully build and respect the "NO_COLOR" env: stdout 1`] = ` +"asset bundle.js x KiB [emitted] (name: main) +asset svg.svg x KiB [emitted] [from: svg.svg] (auxiliary name: main) +asset index.html x bytes [emitted] [from: index.html] (auxiliary name: main) +runtime modules x KiB x modules +cacheable modules x bytes +./foo.js x bytes [built] [code generated] +./svg.svg x bytes [built] [code generated] +./index.html x bytes [built] [code generated] +webpack x.x.x compiled successfully in x ms" +`; + exports[`logging should logging on successfully build and respect the "stats" option from configuration with custom object value: stderr 1`] = `""`; exports[`logging should logging on successfully build and respect the "stats" option from configuration with custom object value: stdout 1`] = ` @@ -262,6 +276,109 @@ asset bundle.js x bytes [emitted] (name: main) webpack x.x.x compiled successfully in x ms" `; +exports[`logging should logging on successfully build using the "stats" option for middleware with object value and no colors: stderr 1`] = `""`; + +exports[`logging should logging on successfully build using the "stats" option for middleware with object value and no colors: stdout 1`] = ` +"asset bundle.js x KiB [emitted] (name: main) +asset svg.svg x KiB [emitted] [from: svg.svg] (auxiliary name: main) +asset index.html x bytes [emitted] [from: index.html] (auxiliary name: main)" +`; + +exports[`logging should logging on successfully build using the "stats" option for middleware with object value: stderr 1`] = `""`; + +exports[`logging should logging on successfully build using the "stats" option for middleware with object value: stdout 1`] = ` +"asset bundle.js x KiB [emitted] (name: main) +asset svg.svg x KiB [emitted] [from: svg.svg] (auxiliary name: main) +asset index.html x bytes [emitted] [from: index.html] (auxiliary name: main)" +`; + +exports[`logging should logging on successfully build using the "stats" option for middleware with the "false" value: stderr 1`] = `""`; + +exports[`logging should logging on successfully build using the "stats" option for middleware with the "false" value: stdout 1`] = `""`; + +exports[`logging should logging on successfully build using the "stats" option for middleware with the "none" value: stderr 1`] = `""`; + +exports[`logging should logging on successfully build using the "stats" option for middleware with the "none" value: stdout 1`] = `""`; + +exports[`logging should logging on successfully build using the "stats" option for middleware with the "normal" value: stderr 1`] = `""`; + +exports[`logging should logging on successfully build using the "stats" option for middleware with the "normal" value: stdout 1`] = ` +"asset bundle.js x KiB [emitted] (name: main) +asset svg.svg x KiB [emitted] [from: svg.svg] (auxiliary name: main) +asset index.html x bytes [emitted] [from: index.html] (auxiliary name: main) +runtime modules x KiB x modules +cacheable modules x bytes +./foo.js x bytes [built] [code generated] +./svg.svg x bytes [built] [code generated] +./index.html x bytes [built] [code generated] +webpack x.x.x compiled successfully in x ms" +`; + +exports[`logging should logging on successfully build using the "stats" option for middleware with the "true" value: stderr 1`] = `""`; + +exports[`logging should logging on successfully build using the "stats" option for middleware with the "true" value: stdout 1`] = ` +"asset bundle.js x KiB [emitted] (name: main) +asset svg.svg x KiB [emitted] [from: svg.svg] (auxiliary name: main) +asset index.html x bytes [emitted] [from: index.html] (auxiliary name: main) +runtime modules x KiB x modules +cacheable modules x bytes +./foo.js x bytes [built] [code generated] +./svg.svg x bytes [built] [code generated] +./index.html x bytes [built] [code generated] +webpack x.x.x compiled successfully in x ms" +`; + +exports[`logging should logging on successfully build using the "stats" option for middleware with the "verbose" value: stderr 1`] = `""`; + +exports[`logging should logging on successfully build using the "stats" option for middleware with the "verbose" value: stdout 1`] = ` +"PublicPath: auto +asset bundle.js x KiB {main} [emitted] (name: main) +asset svg.svg x KiB ({main}) [emitted] [from: svg.svg] (auxiliary name: main) +asset index.html x bytes ({main}) [emitted] [from: index.html] (auxiliary name: main) +Entrypoint main x KiB (x KiB) = bundle.js 2 auxiliary assets +chunk {main} (runtime: main) bundle.js (xxxx) x bytes (xxxx) x KiB (xxxx) [entry] [rendered] +> ./foo.js main +runtime modules x KiB +webpack/runtime/define property getters x bytes {main} [code generated] +[no exports] +[used exports unknown] +webpack/runtime/global x bytes {main} [code generated] +[no exports] +[used exports unknown] +webpack/runtime/hasOwnProperty shorthand x bytes {main} [code generated] +[no exports] +[used exports unknown] +webpack/runtime/make namespace object x bytes {main} [code generated] +[no exports] +[used exports unknown] +webpack/runtime/publicPath x bytes {main} [code generated] +[no exports] +[used exports unknown] +cacheable modules x bytes +./foo.js x bytes {main} [depth 0] [built] [code generated] +[used exports unknown] +entry ./foo.js main +./index.html x bytes {main} [depth 1] [dependent] [built] [code generated] +[exports: default] +[used exports unknown] +cjs require ./index.html [./foo.js] 4:0-23 +./svg.svg x bytes {main} [depth 1] [dependent] [built] [code generated] +[exports: default] +[used exports unknown] +cjs require ./svg.svg [./foo.js] 3:0-20 + + +LOG from xxx" +`; + +exports[`logging should logging on successfully build using the "stats" option for middleware with the object value and colors: stderr 1`] = `""`; + +exports[`logging should logging on successfully build using the "stats" option for middleware with the object value and colors: stdout 1`] = ` +"asset bundle.js x KiB [emitted] (name: main) +asset svg.svg x KiB [emitted] [from: svg.svg] (auxiliary name: main) +asset index.html x bytes [emitted] [from: index.html] (auxiliary name: main)" +`; + exports[`logging should logging on successfully build when the 'stats' doesn't exist: stderr 1`] = `""`; exports[`logging should logging on successfully build when the 'stats' doesn't exist: stdout 1`] = ` @@ -290,6 +407,76 @@ cacheable modules x bytes webpack x.x.x compiled successfully in x ms" `; +exports[`logging should logging on successfully multi compiler build using the "stats" option for middleware with object value and colors: stderr 1`] = `""`; + +exports[`logging should logging on successfully multi compiler build using the "stats" option for middleware with object value and colors: stdout 1`] = ` +"asset svg.svg x KiB [emitted] [from: svg.svg] (auxiliary name: main) +asset bundle.js x KiB [emitted] (name: main) +asset index.html x bytes [emitted] [from: index.html] (auxiliary name: main) + +asset bundle.js x bytes [emitted] (name: main)" +`; + +exports[`logging should logging on successfully multi compiler build using the "stats" option for middleware with object value and no colors: stderr 1`] = `""`; + +exports[`logging should logging on successfully multi compiler build using the "stats" option for middleware with object value and no colors: stdout 1`] = ` +"asset svg.svg x KiB [emitted] [from: svg.svg] (auxiliary name: main) +asset bundle.js x KiB [emitted] (name: main) +asset index.html x bytes [emitted] [from: index.html] (auxiliary name: main) + +asset bundle.js x bytes [emitted] (name: main)" +`; + +exports[`logging should logging on successfully multi compiler build using the "stats" option for middleware with the "false" value: stderr 1`] = `""`; + +exports[`logging should logging on successfully multi compiler build using the "stats" option for middleware with the "false" value: stdout 1`] = `""`; + +exports[`logging should logging on successfully multi compiler build using the "stats" option for middleware with the "normal" value: stderr 1`] = `""`; + +exports[`logging should logging on successfully multi compiler build using the "stats" option for middleware with the "normal" value: stdout 1`] = ` +"asset svg.svg x KiB [emitted] [from: svg.svg] (auxiliary name: main) +asset bundle.js x KiB [emitted] (name: main) +asset index.html x bytes [emitted] [from: index.html] (auxiliary name: main) +runtime modules x bytes x modules +cacheable modules x bytes +./foo.js x bytes [built] [code generated] +./svg.svg x bytes [built] [code generated] +./index.html x bytes [built] [code generated] +webpack x.x.x compiled successfully in x ms + +asset bundle.js x bytes [emitted] (name: main) +./bar.js x bytes [built] [code generated] +webpack x.x.x compiled successfully in x ms" +`; + +exports[`logging should logging on successfully multi compiler build using the "stats" option for middleware with the "true" value: stderr 1`] = `""`; + +exports[`logging should logging on successfully multi compiler build using the "stats" option for middleware with the "true" value: stdout 1`] = ` +"asset svg.svg x KiB [emitted] [from: svg.svg] (auxiliary name: main) +asset bundle.js x KiB [emitted] (name: main) +asset index.html x bytes [emitted] [from: index.html] (auxiliary name: main) +runtime modules x bytes x modules +cacheable modules x bytes +./foo.js x bytes [built] [code generated] +./svg.svg x bytes [built] [code generated] +./index.html x bytes [built] [code generated] +webpack x.x.x compiled successfully in x ms + +asset bundle.js x bytes [emitted] (name: main) +./bar.js x bytes [built] [code generated] +webpack x.x.x compiled successfully in x ms" +`; + +exports[`logging should logging on successfully multi compiler build using the "stats" option for middleware with the object value: stderr 1`] = `""`; + +exports[`logging should logging on successfully multi compiler build using the "stats" option for middleware with the object value: stdout 1`] = ` +"asset svg.svg x KiB [emitted] [from: svg.svg] (auxiliary name: main) +asset bundle.js x KiB [emitted] (name: main) +asset index.html x bytes [emitted] [from: index.html] (auxiliary name: main) + +asset bundle.js x bytes [emitted] (name: main)" +`; + exports[`logging should logging on unsuccessful build in multi-compiler: stderr 1`] = `""`; exports[`logging should logging on unsuccessful build in multi-compiler: stdout 1`] = ` diff --git a/test/__snapshots__/validation-options.test.js.snap.webpack4 b/test/__snapshots__/validation-options.test.js.snap.webpack4 index 891567ffe..3b46c1351 100644 --- a/test/__snapshots__/validation-options.test.js.snap.webpack4 +++ b/test/__snapshots__/validation-options.test.js.snap.webpack4 @@ -77,6 +77,19 @@ exports[`validation should throw an error on the "serverSideRender" option with -> Instructs the module to enable or disable the server-side rendering mode." `; +exports[`validation should throw an error on the "stats" option with "0" value 1`] = ` +"Invalid options object. Dev Middleware has been initialized using an options object that does not match the API schema. + - options.stats should be one of these: + \\"none\\" | \\"summary\\" | \\"errors-only\\" | \\"errors-warnings\\" | \\"minimal\\" | \\"normal\\" | \\"detailed\\" | \\"verbose\\" | boolean | object { … } + -> Stats options object or preset name. + Details: + * options.stats should be one of these: + \\"none\\" | \\"summary\\" | \\"errors-only\\" | \\"errors-warnings\\" | \\"minimal\\" | \\"normal\\" | \\"detailed\\" | \\"verbose\\" + * options.stats should be a boolean. + * options.stats should be an object: + object { … }" +`; + exports[`validation should throw an error on the "writeToDisk" option with "{}" value 1`] = ` "Invalid options object. Dev Middleware has been initialized using an options object that does not match the API schema. - options.writeToDisk should be one of these: diff --git a/test/__snapshots__/validation-options.test.js.snap.webpack5 b/test/__snapshots__/validation-options.test.js.snap.webpack5 index 891567ffe..3b46c1351 100644 --- a/test/__snapshots__/validation-options.test.js.snap.webpack5 +++ b/test/__snapshots__/validation-options.test.js.snap.webpack5 @@ -77,6 +77,19 @@ exports[`validation should throw an error on the "serverSideRender" option with -> Instructs the module to enable or disable the server-side rendering mode." `; +exports[`validation should throw an error on the "stats" option with "0" value 1`] = ` +"Invalid options object. Dev Middleware has been initialized using an options object that does not match the API schema. + - options.stats should be one of these: + \\"none\\" | \\"summary\\" | \\"errors-only\\" | \\"errors-warnings\\" | \\"minimal\\" | \\"normal\\" | \\"detailed\\" | \\"verbose\\" | boolean | object { … } + -> Stats options object or preset name. + Details: + * options.stats should be one of these: + \\"none\\" | \\"summary\\" | \\"errors-only\\" | \\"errors-warnings\\" | \\"minimal\\" | \\"normal\\" | \\"detailed\\" | \\"verbose\\" + * options.stats should be a boolean. + * options.stats should be an object: + object { … }" +`; + exports[`validation should throw an error on the "writeToDisk" option with "{}" value 1`] = ` "Invalid options object. Dev Middleware has been initialized using an options object that does not match the API schema. - options.writeToDisk should be one of these: diff --git a/test/helpers/runner.js b/test/helpers/runner.js index 2fc5366d0..2cef413a5 100755 --- a/test/helpers/runner.js +++ b/test/helpers/runner.js @@ -5,7 +5,6 @@ const webpack = require('webpack'); const merge = require('deepmerge'); const middleware = require('../../dist').default; - const defaultConfig = require('../fixtures/webpack.config'); const configEntries = []; @@ -36,6 +35,20 @@ compiler.hooks.done.tap('plugin-test', () => { process.stdout.write('compiled-for-tests'); }); +switch (process.env.WEBPACK_DEV_MIDDLEWARE_STATS) { + case 'object': + configMiddleware.stats = { all: false, assets: true }; + break; + case 'object_colors_true': + configMiddleware.stats = { all: false, assets: true, colors: true }; + break; + case 'object_colors_false': + configMiddleware.stats = { all: false, assets: true, colors: false }; + break; + default: + // Nothing +} + try { instance = middleware(compiler, configMiddleware); } catch (error) { diff --git a/test/logging.test.js b/test/logging.test.js index 27fdf70f2..8b30ddd66 100644 --- a/test/logging.test.js +++ b/test/logging.test.js @@ -271,6 +271,7 @@ describe('logging', () => { stdio: 'pipe', env: { WEBPACK_CONFIG: 'webpack.stats-minimal.config', + FORCE_COLOR: true, }, }); } catch (error) { @@ -294,6 +295,7 @@ describe('logging', () => { }); proc.on('exit', () => { + // expect(stdout).toContain('\u001b[1m'); expect(stdoutToSnapshot(stdout)).toMatchSnapshot('stdout'); expect(stderrToSnapshot(stderr)).toMatchSnapshot('stderr'); @@ -309,6 +311,7 @@ describe('logging', () => { stdio: 'pipe', env: { WEBPACK_CONFIG: 'webpack.stats-verbose.config', + FORCE_COLOR: true, }, }); } catch (error) { @@ -332,6 +335,7 @@ describe('logging', () => { }); proc.on('exit', () => { + expect(stdout).toContain('\u001b[1m'); expect(stdoutToSnapshot(stdout)).toMatchSnapshot('stdout'); expect(stderrToSnapshot(stderr)).toMatchSnapshot('stderr'); @@ -347,6 +351,7 @@ describe('logging', () => { stdio: 'pipe', env: { WEBPACK_CONFIG: 'webpack.stats-true.config', + FORCE_COLOR: true, }, }); } catch (error) { @@ -370,6 +375,7 @@ describe('logging', () => { }); proc.on('exit', () => { + expect(stdout).toContain('\u001b[1m'); expect(stdoutToSnapshot(stdout)).toMatchSnapshot('stdout'); expect(stderrToSnapshot(stderr)).toMatchSnapshot('stderr'); @@ -462,8 +468,8 @@ describe('logging', () => { proc = execa(runner, [], { stdio: 'pipe', env: { - FORCE_COLOR: true, WEBPACK_CONFIG: 'webpack.array.config', + FORCE_COLOR: true, }, }); } catch (error) { @@ -503,6 +509,7 @@ describe('logging', () => { stdio: 'pipe', env: { WEBPACK_CONFIG: 'webpack.error.config', + FORCE_COLOR: true, }, }); } catch (error) { @@ -526,6 +533,7 @@ describe('logging', () => { }); proc.on('exit', () => { + expect(stdout).toContain('\u001b[1m'); expect(stdoutToSnapshot(stdout)).toMatchSnapshot('stdout'); expect(stderrToSnapshot(stderr)).toMatchSnapshot('stderr'); @@ -541,6 +549,7 @@ describe('logging', () => { stdio: 'pipe', env: { WEBPACK_CONFIG: 'webpack.array.error.config', + FORCE_COLOR: true, }, }); } catch (error) { @@ -564,6 +573,7 @@ describe('logging', () => { }); proc.on('exit', () => { + expect(stdout).toContain('\u001b[1m'); expect(stdoutToSnapshot(stdout)).toMatchSnapshot('stdout'); expect(stderrToSnapshot(stderr)).toMatchSnapshot('stderr'); @@ -579,6 +589,7 @@ describe('logging', () => { stdio: 'pipe', env: { WEBPACK_CONFIG: 'webpack.warning.config', + FORCE_COLOR: true, }, }); } catch (error) { @@ -602,6 +613,7 @@ describe('logging', () => { }); proc.on('exit', () => { + expect(stdout).toContain('\u001b[1m'); expect(stdoutToSnapshot(stdout)).toMatchSnapshot('stdout'); expect(stderrToSnapshot(stderr)).toMatchSnapshot('stderr'); @@ -617,6 +629,7 @@ describe('logging', () => { stdio: 'pipe', env: { WEBPACK_CONFIG: 'webpack.array.warning.config', + FORCE_COLOR: true, }, }); } catch (error) { @@ -640,6 +653,7 @@ describe('logging', () => { }); proc.on('exit', () => { + expect(stdout).toContain('\u001b[1m'); expect(stdoutToSnapshot(stdout)).toMatchSnapshot('stdout'); expect(stderrToSnapshot(stderr)).toMatchSnapshot('stderr'); @@ -655,6 +669,7 @@ describe('logging', () => { stdio: 'pipe', env: { WEBPACK_CONFIG: 'webpack.array.one-error-one-warning-one-success', + FORCE_COLOR: true, }, }); } catch (error) { @@ -678,6 +693,7 @@ describe('logging', () => { }); proc.on('exit', () => { + expect(stdout).toContain('\u001b[1m'); expect(stdoutToSnapshot(stdout)).toMatchSnapshot('stdout'); expect(stderrToSnapshot(stderr)).toMatchSnapshot('stderr'); @@ -694,6 +710,7 @@ describe('logging', () => { env: { WEBPACK_CONFIG: 'webpack.array.one-error-one-warning-one-success-with-names', + FORCE_COLOR: true, }, }); } catch (error) { @@ -717,6 +734,7 @@ describe('logging', () => { }); proc.on('exit', () => { + expect(stdout).toContain('\u001b[1m'); expect(stdoutToSnapshot(stdout)).toMatchSnapshot('stdout'); expect(stderrToSnapshot(stderr)).toMatchSnapshot('stderr'); @@ -732,6 +750,7 @@ describe('logging', () => { stdio: 'pipe', env: { WEBPACK_CONFIG: 'webpack.array.one-error-one-warning-one-no', + FORCE_COLOR: true, }, }); } catch (error) { @@ -755,6 +774,7 @@ describe('logging', () => { }); proc.on('exit', () => { + expect(stdout).toContain('\u001b[1m'); expect(stdoutToSnapshot(stdout)).toMatchSnapshot('stdout'); expect(stderrToSnapshot(stderr)).toMatchSnapshot('stderr'); @@ -770,6 +790,7 @@ describe('logging', () => { stdio: 'pipe', env: { WEBPACK_CONFIG: 'webpack.array.one-error-one-warning-one-object', + FORCE_COLOR: true, }, }); } catch (error) { @@ -793,6 +814,7 @@ describe('logging', () => { }); proc.on('exit', () => { + expect(stdout).toContain('\u001b[1m'); expect(stdoutToSnapshot(stdout)).toMatchSnapshot('stdout'); expect(stderrToSnapshot(stderr)).toMatchSnapshot('stderr'); @@ -877,4 +899,615 @@ describe('logging', () => { }); }); } + + it('should logging on successfully build using the "stats" option for middleware with the "true" value', (done) => { + let proc; + + try { + proc = execa(runner, [], { + stdio: 'pipe', + env: { + WEBPACK_CONFIG: 'webpack.config', + WMC_stats: true, + FORCE_COLOR: true, + }, + }); + } catch (error) { + throw error; + } + + let stdout = ''; + let stderr = ''; + + proc.stdout.on('data', (chunk) => { + stdout += chunk.toString(); + + if (/compiled-for-tests/gi.test(stdout)) { + proc.stdin.write('|exit|'); + } + }); + + proc.stderr.on('data', (chunk) => { + stderr += chunk.toString(); + proc.stdin.write('|exit|'); + }); + + proc.on('exit', () => { + expect(stdout).toContain('\u001b[1m'); + expect(stdoutToSnapshot(stdout)).toMatchSnapshot('stdout'); + expect(stderrToSnapshot(stderr)).toMatchSnapshot('stderr'); + + done(); + }); + }); + + it('should logging on successfully build using the "stats" option for middleware with the "false" value', (done) => { + let proc; + + try { + proc = execa(runner, [], { + stdio: 'pipe', + env: { + WEBPACK_CONFIG: 'webpack.config', + WMC_stats: false, + FORCE_COLOR: true, + }, + }); + } catch (error) { + throw error; + } + + let stdout = ''; + let stderr = ''; + + proc.stdout.on('data', (chunk) => { + stdout += chunk.toString(); + + if (/compiled-for-tests/gi.test(stdout)) { + proc.stdin.write('|exit|'); + } + }); + + proc.stderr.on('data', (chunk) => { + stderr += chunk.toString(); + proc.stdin.write('|exit|'); + }); + + proc.on('exit', () => { + expect(stdoutToSnapshot(stdout)).toMatchSnapshot('stdout'); + expect(stderrToSnapshot(stderr)).toMatchSnapshot('stderr'); + + done(); + }); + }); + + it('should logging on successfully build using the "stats" option for middleware with the "none" value', (done) => { + let proc; + + try { + proc = execa(runner, [], { + stdio: 'pipe', + env: { + WEBPACK_CONFIG: 'webpack.config', + WMC_stats: 'none', + FORCE_COLOR: true, + }, + }); + } catch (error) { + throw error; + } + + let stdout = ''; + let stderr = ''; + + proc.stdout.on('data', (chunk) => { + stdout += chunk.toString(); + + if (/compiled-for-tests/gi.test(stdout)) { + proc.stdin.write('|exit|'); + } + }); + + proc.stderr.on('data', (chunk) => { + stderr += chunk.toString(); + proc.stdin.write('|exit|'); + }); + + proc.on('exit', () => { + expect(stdoutToSnapshot(stdout)).toMatchSnapshot('stdout'); + expect(stderrToSnapshot(stderr)).toMatchSnapshot('stderr'); + + done(); + }); + }); + + it('should logging on successfully build using the "stats" option for middleware with the "normal" value', (done) => { + let proc; + + try { + proc = execa(runner, [], { + stdio: 'pipe', + env: { + WEBPACK_CONFIG: 'webpack.config', + WMC_stats: 'normal', + FORCE_COLOR: true, + }, + }); + } catch (error) { + throw error; + } + + let stdout = ''; + let stderr = ''; + + proc.stdout.on('data', (chunk) => { + stdout += chunk.toString(); + + if (/compiled-for-tests/gi.test(stdout)) { + proc.stdin.write('|exit|'); + } + }); + + proc.stderr.on('data', (chunk) => { + stderr += chunk.toString(); + proc.stdin.write('|exit|'); + }); + + proc.on('exit', () => { + expect(stdout).toContain('\u001b[1m'); + expect(stdoutToSnapshot(stdout)).toMatchSnapshot('stdout'); + expect(stderrToSnapshot(stderr)).toMatchSnapshot('stderr'); + + done(); + }); + }); + + it('should logging on successfully build using the "stats" option for middleware with the "verbose" value', (done) => { + let proc; + + try { + proc = execa(runner, [], { + stdio: 'pipe', + env: { + WEBPACK_CONFIG: 'webpack.config', + WMC_stats: 'verbose', + FORCE_COLOR: true, + }, + }); + } catch (error) { + throw error; + } + + let stdout = ''; + let stderr = ''; + + proc.stdout.on('data', (chunk) => { + stdout += chunk.toString(); + + if (/compiled-for-tests/gi.test(stdout)) { + proc.stdin.write('|exit|'); + } + }); + + proc.stderr.on('data', (chunk) => { + stderr += chunk.toString(); + proc.stdin.write('|exit|'); + }); + + proc.on('exit', () => { + expect(stdout).toContain('\u001b[1m'); + expect(stdoutToSnapshot(stdout)).toMatchSnapshot('stdout'); + expect(stderrToSnapshot(stderr)).toMatchSnapshot('stderr'); + + done(); + }); + }); + + it('should logging on successfully build using the "stats" option for middleware with object value', (done) => { + let proc; + + try { + proc = execa(runner, [], { + stdio: 'pipe', + env: { + WEBPACK_CONFIG: 'webpack.config', + WEBPACK_DEV_MIDDLEWARE_STATS: 'object', + FORCE_COLOR: true, + }, + }); + } catch (error) { + throw error; + } + + let stdout = ''; + let stderr = ''; + + proc.stdout.on('data', (chunk) => { + stdout += chunk.toString(); + + if (/compiled-for-tests/gi.test(stdout)) { + proc.stdin.write('|exit|'); + } + }); + + proc.stderr.on('data', (chunk) => { + stderr += chunk.toString(); + proc.stdin.write('|exit|'); + }); + + proc.on('exit', () => { + expect(stdout).toContain('\u001b[1m'); + expect(stdoutToSnapshot(stdout)).toMatchSnapshot('stdout'); + expect(stderrToSnapshot(stderr)).toMatchSnapshot('stderr'); + + done(); + }); + }); + + it('should logging on successfully build using the "stats" option for middleware with the object value and colors', (done) => { + let proc; + + try { + proc = execa(runner, [], { + stdio: 'pipe', + env: { + WEBPACK_CONFIG: 'webpack.config', + WEBPACK_DEV_MIDDLEWARE_STATS: 'object_colors_true', + FORCE_COLOR: true, + }, + }); + } catch (error) { + throw error; + } + + let stdout = ''; + let stderr = ''; + + proc.stdout.on('data', (chunk) => { + stdout += chunk.toString(); + + if (/compiled-for-tests/gi.test(stdout)) { + proc.stdin.write('|exit|'); + } + }); + + proc.stderr.on('data', (chunk) => { + stderr += chunk.toString(); + proc.stdin.write('|exit|'); + }); + + proc.on('exit', () => { + expect(stdout).toContain('\u001b[1m'); + expect(stdoutToSnapshot(stdout)).toMatchSnapshot('stdout'); + expect(stderrToSnapshot(stderr)).toMatchSnapshot('stderr'); + + done(); + }); + }); + + it('should logging on successfully build using the "stats" option for middleware with object value and no colors', (done) => { + let proc; + + try { + proc = execa(runner, [], { + stdio: 'pipe', + env: { + WEBPACK_CONFIG: 'webpack.config', + WEBPACK_DEV_MIDDLEWARE_STATS: 'object_colors_false', + FORCE_COLOR: true, + }, + }); + } catch (error) { + throw error; + } + + let stdout = ''; + let stderr = ''; + + proc.stdout.on('data', (chunk) => { + stdout += chunk.toString(); + + if (/compiled-for-tests/gi.test(stdout)) { + proc.stdin.write('|exit|'); + } + }); + + proc.stderr.on('data', (chunk) => { + stderr += chunk.toString(); + proc.stdin.write('|exit|'); + }); + + proc.on('exit', () => { + expect(stdout).not.toContain('\u001b[1m'); + expect(stdoutToSnapshot(stdout)).toMatchSnapshot('stdout'); + expect(stderrToSnapshot(stderr)).toMatchSnapshot('stderr'); + + done(); + }); + }); + + it('should logging on successfully multi compiler build using the "stats" option for middleware with the "true" value', (done) => { + let proc; + + try { + proc = execa(runner, [], { + stdio: 'pipe', + env: { + WEBPACK_CONFIG: 'webpack.array.config', + WMC_stats: true, + FORCE_COLOR: true, + }, + }); + } catch (error) { + throw error; + } + + let stdout = ''; + let stderr = ''; + + proc.stdout.on('data', (chunk) => { + stdout += chunk.toString(); + + if (/compiled-for-tests/gi.test(stdout)) { + proc.stdin.write('|exit|'); + } + }); + + proc.stderr.on('data', (chunk) => { + stderr += chunk.toString(); + proc.stdin.write('|exit|'); + }); + + proc.on('exit', () => { + expect(stdout).toContain('\u001b[1m'); + expect(stdoutToSnapshot(stdout)).toMatchSnapshot('stdout'); + expect(stderrToSnapshot(stderr)).toMatchSnapshot('stderr'); + + done(); + }); + }); + + it('should logging on successfully multi compiler build using the "stats" option for middleware with the "false" value', (done) => { + let proc; + + try { + proc = execa(runner, [], { + stdio: 'pipe', + env: { + WEBPACK_CONFIG: 'webpack.array.config', + WMC_stats: false, + FORCE_COLOR: true, + }, + }); + } catch (error) { + throw error; + } + + let stdout = ''; + let stderr = ''; + + proc.stdout.on('data', (chunk) => { + stdout += chunk.toString(); + + if (/compiled-for-tests/gi.test(stdout)) { + proc.stdin.write('|exit|'); + } + }); + + proc.stderr.on('data', (chunk) => { + stderr += chunk.toString(); + proc.stdin.write('|exit|'); + }); + + proc.on('exit', () => { + expect(stdoutToSnapshot(stdout)).toMatchSnapshot('stdout'); + expect(stderrToSnapshot(stderr)).toMatchSnapshot('stderr'); + + done(); + }); + }); + + it('should logging on successfully multi compiler build using the "stats" option for middleware with the "normal" value', (done) => { + let proc; + + try { + proc = execa(runner, [], { + stdio: 'pipe', + env: { + WEBPACK_CONFIG: 'webpack.array.config', + WMC_stats: 'normal', + FORCE_COLOR: true, + }, + }); + } catch (error) { + throw error; + } + + let stdout = ''; + let stderr = ''; + + proc.stdout.on('data', (chunk) => { + stdout += chunk.toString(); + + if (/compiled-for-tests/gi.test(stdout)) { + proc.stdin.write('|exit|'); + } + }); + + proc.stderr.on('data', (chunk) => { + stderr += chunk.toString(); + proc.stdin.write('|exit|'); + }); + + proc.on('exit', () => { + expect(stdout).toContain('\u001b[1m'); + expect(stdoutToSnapshot(stdout)).toMatchSnapshot('stdout'); + expect(stderrToSnapshot(stderr)).toMatchSnapshot('stderr'); + + done(); + }); + }); + + it('should logging on successfully multi compiler build using the "stats" option for middleware with the object value', (done) => { + let proc; + + try { + proc = execa(runner, [], { + stdio: 'pipe', + env: { + WEBPACK_CONFIG: 'webpack.array.config', + WEBPACK_DEV_MIDDLEWARE_STATS: 'object', + FORCE_COLOR: true, + }, + }); + } catch (error) { + throw error; + } + + let stdout = ''; + let stderr = ''; + + proc.stdout.on('data', (chunk) => { + stdout += chunk.toString(); + + if (/compiled-for-tests/gi.test(stdout)) { + proc.stdin.write('|exit|'); + } + }); + + proc.stderr.on('data', (chunk) => { + stderr += chunk.toString(); + proc.stdin.write('|exit|'); + }); + + proc.on('exit', () => { + expect(stdout).toContain('\u001b[1m'); + expect(stdoutToSnapshot(stdout)).toMatchSnapshot('stdout'); + expect(stderrToSnapshot(stderr)).toMatchSnapshot('stderr'); + + done(); + }); + }); + + it('should logging on successfully multi compiler build using the "stats" option for middleware with object value and colors', (done) => { + let proc; + + try { + proc = execa(runner, [], { + stdio: 'pipe', + env: { + WEBPACK_CONFIG: 'webpack.array.config', + WEBPACK_DEV_MIDDLEWARE_STATS: 'object_colors_true', + FORCE_COLOR: true, + }, + }); + } catch (error) { + throw error; + } + + let stdout = ''; + let stderr = ''; + + proc.stdout.on('data', (chunk) => { + stdout += chunk.toString(); + + if (/compiled-for-tests/gi.test(stdout)) { + proc.stdin.write('|exit|'); + } + }); + + proc.stderr.on('data', (chunk) => { + stderr += chunk.toString(); + proc.stdin.write('|exit|'); + }); + + proc.on('exit', () => { + expect(stdout).toContain('\u001b[1m'); + expect(stdoutToSnapshot(stdout)).toMatchSnapshot('stdout'); + expect(stderrToSnapshot(stderr)).toMatchSnapshot('stderr'); + + done(); + }); + }); + + it('should logging on successfully multi compiler build using the "stats" option for middleware with object value and no colors', (done) => { + let proc; + + try { + proc = execa(runner, [], { + stdio: 'pipe', + env: { + WEBPACK_CONFIG: 'webpack.array.config', + WEBPACK_DEV_MIDDLEWARE_STATS: 'object_colors_false', + FORCE_COLOR: true, + }, + }); + } catch (error) { + throw error; + } + + let stdout = ''; + let stderr = ''; + + proc.stdout.on('data', (chunk) => { + stdout += chunk.toString(); + + if (/compiled-for-tests/gi.test(stdout)) { + proc.stdin.write('|exit|'); + } + }); + + proc.stderr.on('data', (chunk) => { + stderr += chunk.toString(); + proc.stdin.write('|exit|'); + }); + + proc.on('exit', () => { + expect(stdout).not.toContain('\u001b[1m'); + expect(stdoutToSnapshot(stdout)).toMatchSnapshot('stdout'); + expect(stderrToSnapshot(stderr)).toMatchSnapshot('stderr'); + + done(); + }); + }); + + it('should logging on successfully build and respect the "NO_COLOR" env', (done) => { + let proc; + + try { + proc = execa(runner, [], { + stdio: 'pipe', + env: { + WEBPACK_CONFIG: 'webpack.config', + NO_COLOR: true, + }, + }); + } catch (error) { + throw error; + } + + let stdout = ''; + let stderr = ''; + + proc.stdout.on('data', (chunk) => { + stdout += chunk.toString(); + + if (/compiled-for-tests/gi.test(stdout)) { + proc.stdin.write('|exit|'); + } + }); + + proc.stderr.on('data', (chunk) => { + stderr += chunk.toString(); + proc.stdin.write('|exit|'); + }); + + proc.on('exit', () => { + expect(stdout).not.toContain('\u001b[1m'); + expect(stdoutToSnapshot(stdout)).toMatchSnapshot('stdout'); + expect(stderrToSnapshot(stderr)).toMatchSnapshot('stderr'); + + done(); + }); + }); }); diff --git a/test/utils/setupHooks.test.js b/test/utils/setupHooks.test.js index dca7001fb..2aca7b7aa 100644 --- a/test/utils/setupHooks.test.js +++ b/test/utils/setupHooks.test.js @@ -20,6 +20,7 @@ describe('setupHooks', () => { beforeEach(() => { nextTick = jest.spyOn(process, 'nextTick').mockImplementation(() => {}); context = { + options: {}, compiler: { hooks: { watchRun: { diff --git a/test/validation-options.test.js b/test/validation-options.test.js index 719e5c895..1d2d9c49e 100644 --- a/test/validation-options.test.js +++ b/test/validation-options.test.js @@ -44,6 +44,10 @@ describe('validation', () => { success: [true, false, 'foo'], failure: [0, {}], }, + stats: { + success: [true, false, 'normal', 'verbose', { all: false, assets: true }], + failure: [0], + }, }; function stringifyValue(value) {