From 9f19c6e8084201d8654a9815e50d0c5fa639e4f4 Mon Sep 17 00:00:00 2001 From: Dean Shub Date: Sun, 11 Apr 2021 12:34:18 +0300 Subject: [PATCH 1/4] Fixes #417 missing module chunks --- src/analyzer.js | 2 +- test/analyzer.js | 17 + .../with-missing-module-chunks/stats.json | 502 ++++++++++++++++++ .../with-missing-module-chunks/valid-chunk.js | 1 + 4 files changed, 521 insertions(+), 1 deletion(-) create mode 100644 test/stats/with-missing-module-chunks/stats.json create mode 100644 test/stats/with-missing-module-chunks/valid-chunk.js diff --git a/src/analyzer.js b/src/analyzer.js index 5b76c258..be11bbf1 100644 --- a/src/analyzer.js +++ b/src/analyzer.js @@ -190,7 +190,7 @@ function getBundleModules(bundleStats) { function assetHasModule(statAsset, statModule) { // Checking if this module is the part of asset chunks - return statModule.chunks.some(moduleChunk => + return (statModule.chunks || []).some(moduleChunk => statAsset.chunks.includes(moduleChunk) ); } diff --git a/test/analyzer.js b/test/analyzer.js index 9a1cdcc8..4983ff1b 100644 --- a/test/analyzer.js +++ b/test/analyzer.js @@ -131,6 +131,23 @@ describe('Analyzer', function () { }); }); + it('should gracefully process missing chunks', async function () { + generateReportFrom('with-missing-module-chunks/stats.json'); + const chartData = await getChartData(); + const invalidChunk = _.find(chartData, {label: 'invalid-chunk.js'}); + expect(invalidChunk).to.exist; + expect(invalidChunk.statSize).to.equal(24); + forEachChartItem([invalidChunk], item => { + expect(typeof item.statSize).to.equal('number'); + expect(item.parsedSize).to.be.undefined; + }); + const validChunk = _.find(chartData, {label: 'valid-chunk.js'}); + forEachChartItem([validChunk], item => { + expect(typeof item.statSize).to.equal('number'); + expect(typeof item.parsedSize).to.equal('number'); + }); + }); + it('should support stats files with js modules chunk', async function () { generateReportFrom('with-modules-chunk.json'); await expectValidReport({bundleLabel: 'bundle.mjs'}); diff --git a/test/stats/with-missing-module-chunks/stats.json b/test/stats/with-missing-module-chunks/stats.json new file mode 100644 index 00000000..4aa432d7 --- /dev/null +++ b/test/stats/with-missing-module-chunks/stats.json @@ -0,0 +1,502 @@ +{ + "errors": [], + "warnings": [], + "version": "4.8.3", + "hash": "9deae6a8259cab8aa857", + "time": 563, + "builtAt": 1526827103238, + "publicPath": "", + "outputPath": "/Volumes/Work/webpack-bundle-analyzer/test/output", + "assetsByChunkName": { + "invalid": "invalid-chunk.js", + "valid": "valid-chunk.js" + }, + "assets": [ + { + "name": "invalid-chunk.js", + "size": 568, + "chunks": [ + 0 + ], + "chunkNames": [ + "invalid" + ], + "emitted": true + }, + { + "name": "valid-chunk.js", + "size": 590, + "chunks": [ + 1 + ], + "chunkNames": [ + "valid" + ], + "emitted": true + } + ], + "filteredAssets": 0, + "entrypoints": { + "valid": { + "chunks": [ + 1 + ], + "assets": [ + "valid-chunk.js" + ], + "children": {}, + "childAssets": {} + }, + "invalid": { + "chunks": [ + 0 + ], + "assets": [ + "invalid-chunk.js" + ], + "children": {}, + "childAssets": {} + } + }, + "namedChunkGroups": { + "valid": { + "chunks": [ + 1 + ], + "assets": [ + "valid-chunk.js" + ], + "children": {}, + "childAssets": {} + }, + "invalid": { + "chunks": [ + 0 + ], + "assets": [ + "invalid-chunk.js" + ], + "children": {}, + "childAssets": {} + } + }, + "chunks": [ + { + "id": 0, + "rendered": true, + "initial": true, + "entry": true, + "size": 24, + "names": [ + "invalid" + ], + "files": [ + "invalid-chunk.js" + ], + "hash": "8582161dc498aae7630a", + "siblings": [], + "parents": [], + "children": [], + "childrenByOrder": {}, + "modules": [ + { + "id": 1, + "identifier": "/Volumes/Work/webpack-bundle-analyzer/test/invalid-chunk/invalid.js", + "name": "./invalid.js", + "index": 2, + "index2": 2, + "size": 24, + "cacheable": true, + "built": true, + "optional": false, + "prefetched": false, + "issuer": null, + "issuerId": null, + "issuerName": null, + "issuerPath": null, + "failed": false, + "errors": 0, + "warnings": 0, + "assets": [], + "reasons": [ + { + "moduleId": null, + "moduleIdentifier": null, + "module": null, + "moduleName": null, + "type": "single entry", + "userRequest": "./invalid.js", + "loc": "invalid" + } + ], + "usedExports": true, + "providedExports": null, + "optimizationBailout": [ + "ModuleConcatenation bailout: Module is not an ECMAScript module" + ], + "depth": 0, + "source": "console.log('invalid');\n" + } + ], + "filteredModules": 0, + "origins": [ + { + "module": "", + "moduleIdentifier": "", + "moduleName": "", + "loc": "invalid", + "request": "./invalid.js", + "reasons": [] + } + ] + }, + { + "id": 1, + "rendered": true, + "initial": true, + "entry": true, + "size": 70, + "names": [ + "valid" + ], + "files": [ + "valid-chunk.js" + ], + "hash": "7c1fb8000ed732072651", + "siblings": [], + "parents": [], + "children": [], + "childrenByOrder": {}, + "modules": [ + { + "id": 0, + "identifier": "/Volumes/Work/webpack-bundle-analyzer/test/invalid-chunk/valid.js d378c6a2195fc2426055093c3fdde76c", + "name": "./valid.js + 1 modules", + "index": 0, + "index2": 1, + "size": 70, + "cacheable": true, + "built": true, + "optional": false, + "prefetched": false, + "chunks": [ + 1 + ], + "issuer": null, + "issuerId": null, + "issuerName": null, + "issuerPath": null, + "failed": false, + "errors": 0, + "warnings": 0, + "assets": [], + "reasons": [ + { + "moduleId": null, + "moduleIdentifier": null, + "module": null, + "moduleName": null, + "type": "single entry", + "userRequest": "./valid.js", + "loc": "valid" + } + ], + "usedExports": true, + "providedExports": [], + "optimizationBailout": [], + "depth": 0, + "modules": [ + { + "id": null, + "identifier": "/Volumes/Work/webpack-bundle-analyzer/test/invalid-chunk/valid.js", + "name": "./valid.js", + "index": 0, + "index2": 1, + "size": 41, + "cacheable": true, + "built": true, + "optional": false, + "prefetched": false, + "chunks": [], + "issuer": null, + "issuerId": null, + "issuerName": null, + "issuerPath": null, + "failed": false, + "errors": 0, + "warnings": 0, + "assets": [], + "reasons": [ + { + "moduleId": null, + "moduleIdentifier": null, + "module": null, + "moduleName": null, + "type": "single entry", + "userRequest": "./valid.js", + "loc": "valid" + } + ], + "usedExports": true, + "providedExports": [], + "optimizationBailout": [ + "ModuleConcatenation bailout: Module is an entry point" + ], + "depth": 0, + "source": "import { a } from './a';\nconsole.log(a);\n" + }, + { + "id": null, + "identifier": "/Volumes/Work/webpack-bundle-analyzer/test/invalid-chunk/a.js", + "name": "./a.js", + "index": 1, + "index2": 0, + "size": 29, + "cacheable": true, + "built": true, + "optional": false, + "prefetched": false, + "chunks": [], + "issuer": "/Volumes/Work/webpack-bundle-analyzer/test/invalid-chunk/valid.js", + "issuerId": null, + "issuerName": "./valid.js", + "issuerPath": [ + { + "id": null, + "identifier": "/Volumes/Work/webpack-bundle-analyzer/test/invalid-chunk/valid.js", + "name": "./valid.js" + } + ], + "failed": false, + "errors": 0, + "warnings": 0, + "assets": [], + "reasons": [ + { + "moduleId": null, + "moduleIdentifier": "/Volumes/Work/webpack-bundle-analyzer/test/invalid-chunk/valid.js", + "module": "./valid.js", + "moduleName": "./valid.js", + "type": "harmony side effect evaluation", + "userRequest": "./a", + "loc": "1:0-24" + }, + { + "moduleId": null, + "moduleIdentifier": "/Volumes/Work/webpack-bundle-analyzer/test/invalid-chunk/valid.js", + "module": "./valid.js", + "moduleName": "./valid.js", + "type": "harmony import specifier", + "userRequest": "./a", + "loc": "2:12-13" + } + ], + "usedExports": [ + "a" + ], + "providedExports": [ + "a" + ], + "optimizationBailout": [], + "depth": 1, + "source": "export const a = 'module a';\n" + } + ], + "filteredModules": 0 + } + ], + "filteredModules": 0, + "origins": [ + { + "module": "", + "moduleIdentifier": "", + "moduleName": "", + "loc": "valid", + "request": "./valid.js", + "reasons": [] + } + ] + } + ], + "modules": [ + { + "id": 0, + "identifier": "/Volumes/Work/webpack-bundle-analyzer/test/invalid-chunk/valid.js d378c6a2195fc2426055093c3fdde76c", + "name": "./valid.js + 1 modules", + "index": 0, + "index2": 1, + "size": 70, + "cacheable": true, + "built": true, + "optional": false, + "prefetched": false, + "chunks": [ + 1 + ], + "issuer": null, + "issuerId": null, + "issuerName": null, + "issuerPath": null, + "failed": false, + "errors": 0, + "warnings": 0, + "assets": [], + "reasons": [ + { + "moduleId": null, + "moduleIdentifier": null, + "module": null, + "moduleName": null, + "type": "single entry", + "userRequest": "./valid.js", + "loc": "valid" + } + ], + "usedExports": true, + "providedExports": [], + "optimizationBailout": [], + "depth": 0, + "modules": [ + { + "id": null, + "identifier": "/Volumes/Work/webpack-bundle-analyzer/test/invalid-chunk/valid.js", + "name": "./valid.js", + "index": 0, + "index2": 1, + "size": 41, + "cacheable": true, + "built": true, + "optional": false, + "prefetched": false, + "chunks": [], + "issuer": null, + "issuerId": null, + "issuerName": null, + "issuerPath": null, + "failed": false, + "errors": 0, + "warnings": 0, + "assets": [], + "reasons": [ + { + "moduleId": null, + "moduleIdentifier": null, + "module": null, + "moduleName": null, + "type": "single entry", + "userRequest": "./valid.js", + "loc": "valid" + } + ], + "usedExports": true, + "providedExports": [], + "optimizationBailout": [ + "ModuleConcatenation bailout: Module is an entry point" + ], + "depth": 0, + "source": "import { a } from './a';\nconsole.log(a);\n" + }, + { + "id": null, + "identifier": "/Volumes/Work/webpack-bundle-analyzer/test/invalid-chunk/a.js", + "name": "./a.js", + "index": 1, + "index2": 0, + "size": 29, + "cacheable": true, + "built": true, + "optional": false, + "prefetched": false, + "chunks": [], + "issuer": "/Volumes/Work/webpack-bundle-analyzer/test/invalid-chunk/valid.js", + "issuerId": null, + "issuerName": "./valid.js", + "issuerPath": [ + { + "id": null, + "identifier": "/Volumes/Work/webpack-bundle-analyzer/test/invalid-chunk/valid.js", + "name": "./valid.js" + } + ], + "failed": false, + "errors": 0, + "warnings": 0, + "assets": [], + "reasons": [ + { + "moduleId": null, + "moduleIdentifier": "/Volumes/Work/webpack-bundle-analyzer/test/invalid-chunk/valid.js", + "module": "./valid.js", + "moduleName": "./valid.js", + "type": "harmony side effect evaluation", + "userRequest": "./a", + "loc": "1:0-24" + }, + { + "moduleId": null, + "moduleIdentifier": "/Volumes/Work/webpack-bundle-analyzer/test/invalid-chunk/valid.js", + "module": "./valid.js", + "moduleName": "./valid.js", + "type": "harmony import specifier", + "userRequest": "./a", + "loc": "2:12-13" + } + ], + "usedExports": [ + "a" + ], + "providedExports": [ + "a" + ], + "optimizationBailout": [], + "depth": 1, + "source": "export const a = 'module a';\n" + } + ], + "filteredModules": 0 + }, + { + "id": 1, + "identifier": "/Volumes/Work/webpack-bundle-analyzer/test/invalid-chunk/invalid.js", + "name": "./invalid.js", + "index": 2, + "index2": 2, + "size": 24, + "cacheable": true, + "built": true, + "optional": false, + "prefetched": false, + "chunks": [ + 0 + ], + "issuer": null, + "issuerId": null, + "issuerName": null, + "issuerPath": null, + "failed": false, + "errors": 0, + "warnings": 0, + "assets": [], + "reasons": [ + { + "moduleId": null, + "moduleIdentifier": null, + "module": null, + "moduleName": null, + "type": "single entry", + "userRequest": "./invalid.js", + "loc": "invalid" + } + ], + "usedExports": true, + "providedExports": null, + "optimizationBailout": [ + "ModuleConcatenation bailout: Module is not an ECMAScript module" + ], + "depth": 0, + "source": "console.log('invalid');\n" + } + ], + "filteredModules": 0, + "children": [] +} diff --git a/test/stats/with-missing-module-chunks/valid-chunk.js b/test/stats/with-missing-module-chunks/valid-chunk.js new file mode 100644 index 00000000..cbb31239 --- /dev/null +++ b/test/stats/with-missing-module-chunks/valid-chunk.js @@ -0,0 +1 @@ +!function(e){var r={};function t(n){if(r[n])return r[n].exports;var o=r[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=e,t.c=r,t.d=function(e,r,n){t.o(e,r)||Object.defineProperty(e,r,{configurable:!1,enumerable:!0,get:n})},t.r=function(e){Object.defineProperty(e,"__esModule",{value:!0})},t.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(r,"a",r),r},t.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},t.p="",t(t.s=0)}([function(e,r,t){"use strict";t.r(r);console.log("module a")}]); \ No newline at end of file From 2fa9757aa4587e0a43cfefd17a3ca5253f6de0c6 Mon Sep 17 00:00:00 2001 From: Dean Shub Date: Sun, 11 Apr 2021 14:25:29 +0300 Subject: [PATCH 2/4] triger build From b243d8b590bdd08296adb8d9a361431af519f515 Mon Sep 17 00:00:00 2001 From: Dean Shub Date: Sun, 11 Apr 2021 14:41:16 +0300 Subject: [PATCH 3/4] test fix --- test/analyzer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/analyzer.js b/test/analyzer.js index 4983ff1b..d8794543 100644 --- a/test/analyzer.js +++ b/test/analyzer.js @@ -136,7 +136,7 @@ describe('Analyzer', function () { const chartData = await getChartData(); const invalidChunk = _.find(chartData, {label: 'invalid-chunk.js'}); expect(invalidChunk).to.exist; - expect(invalidChunk.statSize).to.equal(24); + expect(invalidChunk.statSize).to.equal(586); forEachChartItem([invalidChunk], item => { expect(typeof item.statSize).to.equal('number'); expect(item.parsedSize).to.be.undefined; From a705b1bf02e00db71c88d1d7c5e8fd8d17ac5408 Mon Sep 17 00:00:00 2001 From: Dean Shub Date: Sun, 11 Apr 2021 14:42:14 +0300 Subject: [PATCH 4/4] test fix --- test/analyzer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/analyzer.js b/test/analyzer.js index d8794543..b15e2c05 100644 --- a/test/analyzer.js +++ b/test/analyzer.js @@ -136,7 +136,7 @@ describe('Analyzer', function () { const chartData = await getChartData(); const invalidChunk = _.find(chartData, {label: 'invalid-chunk.js'}); expect(invalidChunk).to.exist; - expect(invalidChunk.statSize).to.equal(586); + expect(invalidChunk.statSize).to.equal(568); forEachChartItem([invalidChunk], item => { expect(typeof item.statSize).to.equal('number'); expect(item.parsedSize).to.be.undefined;