From 4d7f0f907c808b19984e5514ed122bc462ce21aa Mon Sep 17 00:00:00 2001 From: Christoph Tavan Date: Wed, 11 Nov 2020 11:14:22 +0100 Subject: [PATCH 1/2] Fix handling of webpack array configs When trying to analyze a stats.json for a webpack bundle generated off of an array webpack.config.json webpack-bundle-analyzer was throwing: Could't analyze webpack bundle: TypeError: Cannot read property 'assets' of undefined This bug was probably introduced in https://github.com/webpack-contrib/webpack-bundle-analyzer/pull/376 Example webpack config to generate a stats.json file that causes the crash: ```js function getConfig({ config }) { return { mode: 'production', entry: './src/index.js', performance: { hints: 'warning', }, optimization: { minimize: true, }, output: { filename: `${config}-[name].js`, chunkFilename: `${config}-chunk-[name].js`, path: `${__dirname}/`, }, }; } module.exports = [{ config: 'config-1' }, { config: 'config-2' }].map(getConfig); ``` --- CHANGELOG.md | 1 + src/analyzer.js | 2 +- test/analyzer.js | 12 + test/stats/with-array-config/config-1-main.js | 1 + test/stats/with-array-config/config-2-main.js | 1 + test/stats/with-array-config/stats.json | 338 ++++++++++++++++++ 6 files changed, 354 insertions(+), 1 deletion(-) create mode 100644 test/stats/with-array-config/config-1-main.js create mode 100644 test/stats/with-array-config/config-2-main.js create mode 100644 test/stats/with-array-config/stats.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b3554b2..abe38549 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ _Note: Gaps between patch versions are faulty, broken or test releases._ * **Bug Fix** + * Prevent crashes for bundles generated from webpack array configs. ([#394](https://github.com/webpack-contrib/webpack-bundle-analyzer/pull/394) by [@ctavan](https://github.com/ctavan)) * Fix `non-asset` assets causing analyze failure. ([##385](https://github.com/webpack-contrib/webpack-bundle-analyzer/issues/385) by [@ZKHelloworld](https://github.com/ZKHelloworld)) ## 4.1.0 diff --git a/src/analyzer.js b/src/analyzer.js index b1141b97..14078784 100644 --- a/src/analyzer.js +++ b/src/analyzer.js @@ -32,7 +32,7 @@ function getViewerData(bundleStats, bundleDir, opts) { // Sometimes if there are additional child chunks produced add them as child assets, // leave the 1st one as that is considered the 'root' asset. for (let i = 1; i < children.length; i++) { - bundleStats.children[i].assets.forEach((asset) => { + children[i].assets.forEach((asset) => { asset.isChild = true; bundleStats.assets.push(asset); }); diff --git a/test/analyzer.js b/test/analyzer.js index e9e01adc..ac30db9c 100644 --- a/test/analyzer.js +++ b/test/analyzer.js @@ -37,6 +37,18 @@ describe('Analyzer', function () { }); }); + it('should generate report for array webpack.config.js', async function () { + generateReportFrom('with-array-config/stats.json'); + const chartData = await getChartData(); + expect(chartData).to.have.lengthOf(2); + expect(chartData[0]).to.containSubset({ + label: 'config-1-main.js' + }); + expect(chartData[1]).to.containSubset({ + label: 'config-2-main.js' + }); + }); + it('should generate report when worker bundles have dynamic imports', async function () { generateReportFrom('with-worker-loader-dynamic-import/stats.json'); const chartData = await getChartData(); diff --git a/test/stats/with-array-config/config-1-main.js b/test/stats/with-array-config/config-1-main.js new file mode 100644 index 00000000..77236ca2 --- /dev/null +++ b/test/stats/with-array-config/config-1-main.js @@ -0,0 +1 @@ +!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t){console.log("ABC")}]); \ No newline at end of file diff --git a/test/stats/with-array-config/config-2-main.js b/test/stats/with-array-config/config-2-main.js new file mode 100644 index 00000000..77236ca2 --- /dev/null +++ b/test/stats/with-array-config/config-2-main.js @@ -0,0 +1 @@ +!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t){console.log("ABC")}]); \ No newline at end of file diff --git a/test/stats/with-array-config/stats.json b/test/stats/with-array-config/stats.json new file mode 100644 index 00000000..893b5ef3 --- /dev/null +++ b/test/stats/with-array-config/stats.json @@ -0,0 +1,338 @@ +{ + "errors": [], + "warnings": [], + "version": "4.44.2", + "hash": "a30aaa779dd06e8979b1a30aaa779dd06e8979b1", + "children": [ + { + "errors": [], + "warnings": [], + "hash": "a30aaa779dd06e8979b1", + "time": 105, + "builtAt": 1605088887042, + "publicPath": "", + "outputPath": "/webpack-bundle-analyzer-example/", + "assetsByChunkName": { + "main": "config-1-main.js" + }, + "assets": [ + { + "name": "config-1-main.js", + "size": 948, + "chunks": [0], + "chunkNames": ["main"], + "info": {}, + "emitted": true + } + ], + "filteredAssets": 0, + "entrypoints": { + "main": { + "chunks": [0], + "assets": ["config-1-main.js"], + "children": {}, + "childAssets": {} + } + }, + "namedChunkGroups": { + "main": { + "chunks": [0], + "assets": ["config-1-main.js"], + "children": {}, + "childAssets": {} + } + }, + "chunks": [ + { + "id": 0, + "rendered": true, + "initial": true, + "entry": true, + "size": 20, + "names": ["main"], + "files": ["config-1-main.js"], + "hash": "0e20b5164c4e5cda6fe0", + "siblings": [], + "parents": [], + "children": [], + "childrenByOrder": {}, + "modules": [ + { + "id": 0, + "identifier": "/webpack-bundle-analyzer-example/src/index.js", + "name": "./src/index.js", + "index": 0, + "index2": 0, + "size": 20, + "cacheable": true, + "built": true, + "optional": false, + "prefetched": false, + "chunks": [0], + "issuer": null, + "issuerId": null, + "issuerName": null, + "issuerPath": null, + "profile": { + "factory": 35, + "building": 38 + }, + "failed": false, + "errors": 0, + "warnings": 0, + "assets": [], + "reasons": [ + { + "moduleId": null, + "moduleIdentifier": null, + "module": null, + "moduleName": null, + "type": "single entry", + "userRequest": "./src/index.js", + "loc": "main" + } + ], + "usedExports": true, + "providedExports": null, + "optimizationBailout": [ + "ModuleConcatenation bailout: Module is not an ECMAScript module" + ], + "depth": 0, + "source": "console.log('ABC');\n" + } + ], + "filteredModules": 0, + "origins": [ + { + "module": "", + "moduleIdentifier": "", + "moduleName": "", + "loc": "main", + "request": "./src/index.js", + "reasons": [] + } + ] + } + ], + "modules": [ + { + "id": 0, + "identifier": "/webpack-bundle-analyzer-example/src/index.js", + "name": "./src/index.js", + "index": 0, + "index2": 0, + "size": 20, + "cacheable": true, + "built": true, + "optional": false, + "prefetched": false, + "chunks": [0], + "issuer": null, + "issuerId": null, + "issuerName": null, + "issuerPath": null, + "profile": { + "factory": 35, + "building": 38 + }, + "failed": false, + "errors": 0, + "warnings": 0, + "assets": [], + "reasons": [ + { + "moduleId": null, + "moduleIdentifier": null, + "module": null, + "moduleName": null, + "type": "single entry", + "userRequest": "./src/index.js", + "loc": "main" + } + ], + "usedExports": true, + "providedExports": null, + "optimizationBailout": [ + "ModuleConcatenation bailout: Module is not an ECMAScript module" + ], + "depth": 0, + "source": "console.log('ABC');\n" + } + ], + "filteredModules": 0, + "logging": { + "webpack.buildChunkGraph.visitModules": { + "entries": [], + "filteredEntries": 2, + "debug": false + } + }, + "children": [] + }, + { + "errors": [], + "warnings": [], + "hash": "a30aaa779dd06e8979b1", + "time": 88, + "builtAt": 1605088887043, + "publicPath": "", + "outputPath": "/webpack-bundle-analyzer-example/", + "assetsByChunkName": { + "main": "config-2-main.js" + }, + "assets": [ + { + "name": "config-2-main.js", + "size": 948, + "chunks": [0], + "chunkNames": ["main"], + "info": {}, + "emitted": true + } + ], + "filteredAssets": 0, + "entrypoints": { + "main": { + "chunks": [0], + "assets": ["config-2-main.js"], + "children": {}, + "childAssets": {} + } + }, + "namedChunkGroups": { + "main": { + "chunks": [0], + "assets": ["config-2-main.js"], + "children": {}, + "childAssets": {} + } + }, + "chunks": [ + { + "id": 0, + "rendered": true, + "initial": true, + "entry": true, + "size": 20, + "names": ["main"], + "files": ["config-2-main.js"], + "hash": "0e20b5164c4e5cda6fe0", + "siblings": [], + "parents": [], + "children": [], + "childrenByOrder": {}, + "modules": [ + { + "id": 0, + "identifier": "/webpack-bundle-analyzer-example/src/index.js", + "name": "./src/index.js", + "index": 0, + "index2": 0, + "size": 20, + "cacheable": true, + "built": true, + "optional": false, + "prefetched": false, + "chunks": [0], + "issuer": null, + "issuerId": null, + "issuerName": null, + "issuerPath": null, + "profile": { + "factory": 29, + "building": 9 + }, + "failed": false, + "errors": 0, + "warnings": 0, + "assets": [], + "reasons": [ + { + "moduleId": null, + "moduleIdentifier": null, + "module": null, + "moduleName": null, + "type": "single entry", + "userRequest": "./src/index.js", + "loc": "main" + } + ], + "usedExports": true, + "providedExports": null, + "optimizationBailout": [ + "ModuleConcatenation bailout: Module is not an ECMAScript module" + ], + "depth": 0, + "source": "console.log('ABC');\n" + } + ], + "filteredModules": 0, + "origins": [ + { + "module": "", + "moduleIdentifier": "", + "moduleName": "", + "loc": "main", + "request": "./src/index.js", + "reasons": [] + } + ] + } + ], + "modules": [ + { + "id": 0, + "identifier": "/webpack-bundle-analyzer-example/src/index.js", + "name": "./src/index.js", + "index": 0, + "index2": 0, + "size": 20, + "cacheable": true, + "built": true, + "optional": false, + "prefetched": false, + "chunks": [0], + "issuer": null, + "issuerId": null, + "issuerName": null, + "issuerPath": null, + "profile": { + "factory": 29, + "building": 9 + }, + "failed": false, + "errors": 0, + "warnings": 0, + "assets": [], + "reasons": [ + { + "moduleId": null, + "moduleIdentifier": null, + "module": null, + "moduleName": null, + "type": "single entry", + "userRequest": "./src/index.js", + "loc": "main" + } + ], + "usedExports": true, + "providedExports": null, + "optimizationBailout": [ + "ModuleConcatenation bailout: Module is not an ECMAScript module" + ], + "depth": 0, + "source": "console.log('ABC');\n" + } + ], + "filteredModules": 0, + "logging": { + "webpack.buildChunkGraph.visitModules": { + "entries": [], + "filteredEntries": 2, + "debug": false + } + }, + "children": [] + } + ] +} From 303d801ea12a427bedca330285627f27f83f8b8a Mon Sep 17 00:00:00 2001 From: Christoph Tavan Date: Wed, 11 Nov 2020 13:07:30 +0100 Subject: [PATCH 2/2] Fix changelog entry --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index abe38549..216bf910 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ _Note: Gaps between patch versions are faulty, broken or test releases._ * **Bug Fix** * Prevent crashes for bundles generated from webpack array configs. ([#394](https://github.com/webpack-contrib/webpack-bundle-analyzer/pull/394) by [@ctavan](https://github.com/ctavan)) - * Fix `non-asset` assets causing analyze failure. ([##385](https://github.com/webpack-contrib/webpack-bundle-analyzer/issues/385) by [@ZKHelloworld](https://github.com/ZKHelloworld)) + * Fix `non-asset` assets causing analyze failure. ([#385](https://github.com/webpack-contrib/webpack-bundle-analyzer/issues/385) by [@ZKHelloworld](https://github.com/ZKHelloworld)) ## 4.1.0