diff --git a/src/analyzer.js b/src/analyzer.js index 14078784..5b76c258 100644 --- a/src/analyzer.js +++ b/src/analyzer.js @@ -48,7 +48,7 @@ function getViewerData(bundleStats, bundleDir, opts) { } // Picking only `*.js or *.mjs` assets from bundle that has non-empty `chunks` array - bundleStats.assets = _.filter(bundleStats.assets, asset => { + bundleStats.assets = bundleStats.assets.filter(asset => { // Filter out non 'asset' type asset if type is provided (Webpack 5 add a type to indicate asset types) if (asset.type && asset.type !== 'asset') { return false; @@ -82,7 +82,7 @@ function getViewerData(bundleStats, bundleDir, opts) { } bundlesSources[statAsset.name] = _.pick(bundleInfo, 'src', 'runtimeSrc'); - _.assign(parsedModules, bundleInfo.modules); + Object.assign(parsedModules, bundleInfo.modules); } if (_.isEmpty(bundlesSources)) { @@ -92,7 +92,7 @@ function getViewerData(bundleStats, bundleDir, opts) { } } - const assets = _.transform(bundleStats.assets, (result, statAsset) => { + const assets = bundleStats.assets.reduce((result, statAsset) => { // If asset is a childAsset, then calculate appropriate bundle modules by looking through stats.children const assetBundles = statAsset.isChild ? getChildAssetBundles(bundleStats, statAsset.name) : bundleStats; const modules = assetBundles ? getBundleModules(assetBundles) : []; @@ -144,22 +144,21 @@ function getViewerData(bundleStats, bundleDir, opts) { asset.modules = assetModules; asset.tree = createModulesTree(asset.modules); + return result; }, {}); - return _.transform(assets, (result, asset, filename) => { - result.push({ - label: filename, - isAsset: true, - // Not using `asset.size` here provided by Webpack because it can be very confusing when `UglifyJsPlugin` is used. - // In this case all module sizes from stats file will represent unminified module sizes, but `asset.size` will - // be the size of minified bundle. - // Using `asset.size` only if current asset doesn't contain any modules (resulting size equals 0) - statSize: asset.tree.size || asset.size, - parsedSize: asset.parsedSize, - gzipSize: asset.gzipSize, - groups: _.invokeMap(asset.tree.children, 'toChartData') - }); - }, []); + return Object.entries(assets).map(([filename, asset]) => ({ + label: filename, + isAsset: true, + // Not using `asset.size` here provided by Webpack because it can be very confusing when `UglifyJsPlugin` is used. + // In this case all module sizes from stats file will represent unminified module sizes, but `asset.size` will + // be the size of minified bundle. + // Using `asset.size` only if current asset doesn't contain any modules (resulting size equals 0) + statSize: asset.tree.size || asset.size, + parsedSize: asset.parsedSize, + gzipSize: asset.gzipSize, + groups: _.invokeMap(asset.tree.children, 'toChartData') + })); } function readStatsFromFile(filename) { @@ -169,7 +168,7 @@ function readStatsFromFile(filename) { } function getChildAssetBundles(bundleStats, assetName) { - return _.find(bundleStats.children, (c) => + return (bundleStats.children || []).find((c) => _(c.assetsByChunkName) .values() .flatten() @@ -191,8 +190,8 @@ function getBundleModules(bundleStats) { function assetHasModule(statAsset, statModule) { // Checking if this module is the part of asset chunks - return _.some(statModule.chunks, moduleChunk => - _.includes(statAsset.chunks, moduleChunk) + return statModule.chunks.some(moduleChunk => + statAsset.chunks.includes(moduleChunk) ); } @@ -207,7 +206,7 @@ function isRuntimeModule(statModule) { function createModulesTree(modules) { const root = new Folder('.'); - _.each(modules, module => root.addModule(module)); + modules.forEach(module => root.addModule(module)); root.mergeNestedFolders(); return root; diff --git a/src/bin/analyzer.js b/src/bin/analyzer.js index 88d8dad0..5303578c 100755 --- a/src/bin/analyzer.js +++ b/src/bin/analyzer.js @@ -2,7 +2,6 @@ const {resolve, dirname} = require('path'); -const _ = require('lodash'); const commander = require('commander'); const {magenta} = require('chalk'); @@ -157,7 +156,7 @@ function showHelp(error) { } function br(str) { - return `\n${_.repeat(' ', 28)}${str}`; + return `\n${' '.repeat(28)}${str}`; } function array() { diff --git a/src/parseUtils.js b/src/parseUtils.js index bce9878c..ec4ec2ab 100644 --- a/src/parseUtils.js +++ b/src/parseUtils.js @@ -135,7 +135,7 @@ function parseBundle(bundlePath) { // Walking into arguments because some of plugins (e.g. `DedupePlugin`) or some Webpack // features (e.g. `umd` library output) can wrap modules list into additional IIFE. - _.each(args, arg => c(arg, state)); + args.forEach(arg => c(arg, state)); } } ); @@ -161,9 +161,8 @@ function parseBundle(bundlePath) { * Returns bundle source except modules */ function getBundleRuntime(content, modulesLocations) { - const sortedLocations = _(modulesLocations) - .values() - .sortBy('start'); + const sortedLocations = Object.values(modulesLocations || {}) + .sort((a, b) => a.start - b.start); let result = ''; let lastIndex = 0; @@ -214,8 +213,8 @@ function isSimpleModulesList(node) { function isModulesHash(node) { return ( node.type === 'ObjectExpression' && - _(node.properties) - .map('value') + node.properties + .map(node => node.value) .every(isModuleWrapper) ); } @@ -223,7 +222,7 @@ function isModulesHash(node) { function isModulesArray(node) { return ( node.type === 'ArrayExpression' && - _.every(node.elements, elem => + node.elements.every(elem => // Some of array items may be skipped because there is no module with such id !elem || isModuleWrapper(elem) @@ -276,7 +275,7 @@ function isChunkIds(node) { // Array of numeric or string ids. Chunk IDs are strings when NamedChunksPlugin is used return ( node.type === 'ArrayExpression' && - _.every(node.elements, isModuleId) + node.elements.every(isModuleId) ); } @@ -321,10 +320,11 @@ function getModulesLocations(node) { // Modules hash const modulesNodes = node.properties; - return _.transform(modulesNodes, (result, moduleNode) => { + return modulesNodes.reduce((result, moduleNode) => { const moduleId = moduleNode.key.name || moduleNode.key.value; result[moduleId] = getModuleLocation(moduleNode.value); + return result; }, {}); } @@ -342,9 +342,11 @@ function getModulesLocations(node) { node.arguments[0].elements : node.elements; - return _.transform(modulesNodes, (result, moduleNode, i) => { - if (!moduleNode) return; - result[i + minId] = getModuleLocation(moduleNode); + return modulesNodes.reduce((result, moduleNode, i) => { + if (moduleNode) { + result[i + minId] = getModuleLocation(moduleNode); + } + return result; }, {}); } diff --git a/src/tree/BaseFolder.js b/src/tree/BaseFolder.js index c62e9f49..aa0a0032 100644 --- a/src/tree/BaseFolder.js +++ b/src/tree/BaseFolder.js @@ -62,7 +62,7 @@ export default class BaseFolder extends Node { walk(walker, state = {}, deep = true) { let stopped = false; - _.each(this.children, child => { + Object.values(this.children).forEach(child => { if (deep && child.walk) { state = child.walk(walker, state, stop); } else { diff --git a/src/tree/ConcatenatedModule.js b/src/tree/ConcatenatedModule.js index 48c27a0e..19abe28d 100644 --- a/src/tree/ConcatenatedModule.js +++ b/src/tree/ConcatenatedModule.js @@ -15,7 +15,7 @@ export default class ConcatenatedModule extends Module { } fillContentModules() { - _.each(this.data.modules, moduleData => this.addContentModule(moduleData)); + this.data.modules.forEach(moduleData => this.addContentModule(moduleData)); } addContentModule(moduleData) { @@ -28,7 +28,7 @@ export default class ConcatenatedModule extends Module { const [folders, fileName] = [pathParts.slice(0, -1), _.last(pathParts)]; let currentFolder = this; - _.each(folders, folderName => { + folders.forEach(folderName => { let childFolder = currentFolder.getChild(folderName); if (!childFolder) { diff --git a/src/tree/Folder.js b/src/tree/Folder.js index 4e322d83..9bcbc006 100644 --- a/src/tree/Folder.js +++ b/src/tree/Folder.js @@ -30,7 +30,7 @@ export default class Folder extends BaseFolder { const [folders, fileName] = [pathParts.slice(0, -1), _.last(pathParts)]; let currentFolder = this; - _.each(folders, folderName => { + folders.forEach(folderName => { let childNode = currentFolder.getChild(folderName); if ( diff --git a/src/utils.js b/src/utils.js index 9e44084d..be4e40cf 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,4 +1,4 @@ -const {inspect} = require('util'); +const {inspect, types} = require('util'); const _ = require('lodash'); const opener = require('opener'); @@ -15,11 +15,11 @@ function createAssetsFilter(excludePatterns) { pattern = new RegExp(pattern, 'u'); } - if (_.isRegExp(pattern)) { + if (types.isRegExp(pattern)) { return (asset) => pattern.test(asset); } - if (!_.isFunction(pattern)) { + if (typeof pattern !== 'function') { throw new TypeError( `Pattern should be either string, RegExp or a function, but "${inspect(pattern, {depth: 0})}" got.` ); @@ -30,7 +30,7 @@ function createAssetsFilter(excludePatterns) { .value(); if (excludeFunctions.length) { - return (asset) => _.every(excludeFunctions, fn => fn(asset) !== true); + return (asset) => excludeFunctions.every(fn => fn(asset) !== true); } else { return () => true; }