diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d55ad42..e60766f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,9 @@ _Note: Gaps between patch versions are faulty, broken or test releases._ +* **Improvements** + * Add support for .mjs output files ([#252](https://github.com/webpack-contrib/webpack-bundle-analyzer/pull/252), [@jlopezxs](https://github.com/jlopezxs))) + ## 3.1.0 * **Bug Fix** diff --git a/src/analyzer.js b/src/analyzer.js index d7f60e09..62ac9968 100644 --- a/src/analyzer.js +++ b/src/analyzer.js @@ -10,6 +10,7 @@ const {parseBundle} = require('./parseUtils'); const {createAssetsFilter} = require('./utils'); const FILENAME_QUERY_REGEXP = /\?.*$/; +const FILENAME_EXTENSIONS = /\.(js|mjs)$/i; module.exports = { getViewerData, @@ -29,13 +30,13 @@ function getViewerData(bundleStats, bundleDir, opts) { bundleStats = bundleStats.children[0]; } - // Picking only `*.js` assets from bundle that has non-empty `chunks` array + // Picking only `*.js or *.mjs` assets from bundle that has non-empty `chunks` array bundleStats.assets = _.filter(bundleStats.assets, asset => { // Removing query part from filename (yes, somebody uses it for some reason and Webpack supports it) // See #22 asset.name = asset.name.replace(FILENAME_QUERY_REGEXP, ''); - return _.endsWith(asset.name, '.js') && !_.isEmpty(asset.chunks) && isAssetIncluded(asset.name); + return FILENAME_EXTENSIONS.test(asset.name) && !_.isEmpty(asset.chunks) && isAssetIncluded(asset.name); }); // Trying to parse bundle assets and get real module sizes if `bundleDir` is provided diff --git a/test/analyzer.js b/test/analyzer.js index b7c3b025..d5c0a05e 100644 --- a/test/analyzer.js +++ b/test/analyzer.js @@ -101,6 +101,11 @@ describe('Analyzer', function () { 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'}); + }); }); function generateReportFrom(statsFilename) { diff --git a/test/stats/with-modules-chunk.json b/test/stats/with-modules-chunk.json new file mode 100644 index 00000000..1db8a848 --- /dev/null +++ b/test/stats/with-modules-chunk.json @@ -0,0 +1,312 @@ +{ + "errors": [], + "warnings": [], + "version": "1.14.0", + "hash": "4e39ab22a848116a4c15", + "children": [ + { + "errors": [], + "warnings": [], + "version": "1.14.0", + "hash": "4e39ab22a848116a4c15", + "time": 79, + "publicPath": "", + "assetsByChunkName": { + "bundle": "bundle.mjs" + }, + "assets": [ + { + "name": "bundle.mjs", + "size": 1735, + "chunks": [0], + "chunkNames": ["bundle"], + "emitted": true + } + ], + "chunks": [ + { + "id": 0, + "rendered": true, + "initial": true, + "entry": true, + "extraAsync": false, + "size": 141, + "names": ["bundle"], + "files": ["bundle.mjs"], + "hash": "eb0091314b5c4ca75abf", + "parents": [], + "modules": [ + { + "id": 0, + "identifier": "/Volumes/Work/webpack-bundle-analyzer/test/src/index.js", + "name": "./src/index.js", + "index": 0, + "index2": 3, + "size": 54, + "cacheable": true, + "built": true, + "optional": false, + "prefetched": false, + "chunks": [0], + "assets": [], + "issuer": null, + "profile": { + "factory": 19, + "building": 15 + }, + "failed": false, + "errors": 0, + "warnings": 0, + "reasons": [], + "source": "require('./a');\nrequire('./b');\nrequire('./a-clone');\n" + }, + { + "id": 1, + "identifier": "/Volumes/Work/webpack-bundle-analyzer/test/src/a.js", + "name": "./src/a.js", + "index": 1, + "index2": 0, + "size": 29, + "cacheable": true, + "built": true, + "optional": false, + "prefetched": false, + "chunks": [0], + "assets": [], + "issuer": "/Volumes/Work/webpack-bundle-analyzer/test/src/index.js", + "profile": { + "factory": 8, + "building": 6 + }, + "failed": false, + "errors": 0, + "warnings": 0, + "reasons": [ + { + "moduleId": 0, + "moduleIdentifier": "/Volumes/Work/webpack-bundle-analyzer/test/src/index.js", + "module": "./src/index.js", + "moduleName": "./src/index.js", + "type": "cjs require", + "userRequest": "./a", + "loc": "1:0-14" + } + ], + "source": "module.exports = 'module a';\n" + }, + { + "id": 2, + "identifier": "/Volumes/Work/webpack-bundle-analyzer/test/src/b.js", + "name": "./src/b.js", + "index": 2, + "index2": 1, + "size": 29, + "cacheable": true, + "built": true, + "optional": false, + "prefetched": false, + "chunks": [0], + "assets": [], + "issuer": "/Volumes/Work/webpack-bundle-analyzer/test/src/index.js", + "profile": { + "factory": 9, + "building": 5 + }, + "failed": false, + "errors": 0, + "warnings": 0, + "reasons": [ + { + "moduleId": 0, + "moduleIdentifier": "/Volumes/Work/webpack-bundle-analyzer/test/src/index.js", + "module": "./src/index.js", + "moduleName": "./src/index.js", + "type": "cjs require", + "userRequest": "./b", + "loc": "2:0-14" + } + ], + "source": "module.exports = 'module b';\n" + }, + { + "id": 3, + "identifier": "/Volumes/Work/webpack-bundle-analyzer/test/src/a-clone.js", + "name": "./src/a-clone.js", + "index": 3, + "index2": 2, + "size": 29, + "cacheable": true, + "built": true, + "optional": false, + "prefetched": false, + "chunks": [0], + "assets": [], + "issuer": "/Volumes/Work/webpack-bundle-analyzer/test/src/index.js", + "profile": { + "factory": 10, + "building": 5 + }, + "failed": false, + "errors": 0, + "warnings": 0, + "reasons": [ + { + "moduleId": 0, + "moduleIdentifier": "/Volumes/Work/webpack-bundle-analyzer/test/src/index.js", + "module": "./src/index.js", + "moduleName": "./src/index.js", + "type": "cjs require", + "userRequest": "./a-clone", + "loc": "3:0-20" + } + ], + "source": "module.exports = 'module a';\n" + } + ], + "filteredModules": 0, + "origins": [ + { + "moduleId": 0, + "module": "/Volumes/Work/webpack-bundle-analyzer/test/src/index.js", + "moduleIdentifier": "/Volumes/Work/webpack-bundle-analyzer/test/src/index.js", + "moduleName": "./src/index.js", + "loc": "", + "name": "bundle", + "reasons": [] + } + ] + } + ], + "modules": [ + { + "id": 0, + "identifier": "/Volumes/Work/webpack-bundle-analyzer/test/src/index.js", + "name": "./src/index.js", + "index": 0, + "index2": 3, + "size": 54, + "cacheable": true, + "built": true, + "optional": false, + "prefetched": false, + "chunks": [0], + "assets": [], + "issuer": null, + "profile": { + "factory": 19, + "building": 15 + }, + "failed": false, + "errors": 0, + "warnings": 0, + "reasons": [], + "source": "require('./a');\nrequire('./b');\nrequire('./a-clone');\n" + }, + { + "id": 1, + "identifier": "/Volumes/Work/webpack-bundle-analyzer/test/src/a.js", + "name": "./src/a.js", + "index": 1, + "index2": 0, + "size": 29, + "cacheable": true, + "built": true, + "optional": false, + "prefetched": false, + "chunks": [0], + "assets": [], + "issuer": "/Volumes/Work/webpack-bundle-analyzer/test/src/index.js", + "profile": { + "factory": 8, + "building": 6 + }, + "failed": false, + "errors": 0, + "warnings": 0, + "reasons": [ + { + "moduleId": 0, + "moduleIdentifier": "/Volumes/Work/webpack-bundle-analyzer/test/src/index.js", + "module": "./src/index.js", + "moduleName": "./src/index.js", + "type": "cjs require", + "userRequest": "./a", + "loc": "1:0-14" + } + ], + "source": "module.exports = 'module a';\n" + }, + { + "id": 2, + "identifier": "/Volumes/Work/webpack-bundle-analyzer/test/src/b.js", + "name": "./src/b.js", + "index": 2, + "index2": 1, + "size": 29, + "cacheable": true, + "built": true, + "optional": false, + "prefetched": false, + "chunks": [0], + "assets": [], + "issuer": "/Volumes/Work/webpack-bundle-analyzer/test/src/index.js", + "profile": { + "factory": 9, + "building": 5 + }, + "failed": false, + "errors": 0, + "warnings": 0, + "reasons": [ + { + "moduleId": 0, + "moduleIdentifier": "/Volumes/Work/webpack-bundle-analyzer/test/src/index.js", + "module": "./src/index.js", + "moduleName": "./src/index.js", + "type": "cjs require", + "userRequest": "./b", + "loc": "2:0-14" + } + ], + "source": "module.exports = 'module b';\n" + }, + { + "id": 3, + "identifier": "/Volumes/Work/webpack-bundle-analyzer/test/src/a-clone.js", + "name": "./src/a-clone.js", + "index": 3, + "index2": 2, + "size": 29, + "cacheable": true, + "built": true, + "optional": false, + "prefetched": false, + "chunks": [0], + "assets": [], + "issuer": "/Volumes/Work/webpack-bundle-analyzer/test/src/index.js", + "profile": { + "factory": 10, + "building": 5 + }, + "failed": false, + "errors": 0, + "warnings": 0, + "reasons": [ + { + "moduleId": 0, + "moduleIdentifier": "/Volumes/Work/webpack-bundle-analyzer/test/src/index.js", + "module": "./src/index.js", + "moduleName": "./src/index.js", + "type": "cjs require", + "userRequest": "./a-clone", + "loc": "3:0-20" + } + ], + "source": "module.exports = 'module a';\n" + } + ], + "filteredModules": 0, + "children": [] + } + ] +}