Socket
Socket
Sign inDemoInstall

webpack-bundle-analyzer

Package Overview
Dependencies
Maintainers
1
Versions
90
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

webpack-bundle-analyzer - npm Package Compare versions

Comparing version 1.0.1-alpha to 1.1.0-alpha

client/.eslintrc.json

103

lib/analyzer.js
'use strict';
const fs = require('fs');
const path = require('path');
var fs = require('fs');
var path = require('path');
const fileExists = require('file-exists');
const _ = require('lodash');
var fileExists = require('file-exists');
var _ = require('lodash');
const { Folder } = require('../lib/tree');
const { getModuleSizesFromBundle } = require('../lib/parseUtils');
var _require = require('../lib/tree');
var Folder = _require.Folder;
var _require2 = require('../lib/parseUtils');
var getModuleSizesFromBundle = _require2.getModuleSizesFromBundle;
module.exports = {
getChartData,
readStatsFromFile
getChartData: getChartData,
readStatsFromFile: readStatsFromFile
};

@@ -19,18 +25,17 @@

// Picking only `*.js` assets from bundle
bundleStats.assets = _.filter(bundleStats.assets, asset => _.endsWith(asset.name, '.js'));
bundleStats.assets = _.filter(bundleStats.assets, function (asset) {
return _.endsWith(asset.name, '.js');
});
// Real module sizes got by parsing assets
let parsedModuleSizes = null;
var parsedModuleSizes = null;
if (bundleDir) {
// Checking if all assets are exist
const bundleScriptsFound = _.every(bundleStats.assets, statAsset => {
const assetFile = path.resolve(bundleDir, statAsset.name);
const assetExists = fileExists(assetFile);
var bundleScriptsFound = _.every(bundleStats.assets, function (statAsset) {
var assetFile = path.resolve(bundleDir, statAsset.name);
var assetExists = fileExists(assetFile);
if (!assetExists) {
console.log(
`\nUnable to find bundle asset "${assetFile}".\n` +
'Analyzer will use module sizes from stats file.\n'
);
console.log('\nUnable to find bundle asset "' + assetFile + '".\n' + 'Analyzer will use module sizes from stats file.\n');
}

@@ -43,6 +48,4 @@

// Parsing assets and getting real module sizes
parsedModuleSizes = _.transform(bundleStats.assets, (result, statAsset) => {
_.assign(result,
getModuleSizesFromBundle(path.resolve(bundleDir, statAsset.name))
);
parsedModuleSizes = _.transform(bundleStats.assets, function (result, statAsset) {
_.assign(result, getModuleSizesFromBundle(path.resolve(bundleDir, statAsset.name)));
}, {});

@@ -52,14 +55,14 @@ }

const assets = _.transform(bundleStats.assets, (result, statAsset) => {
const bundleFilename = statAsset.name;
const asset = result[bundleFilename] = _.pick(statAsset, 'size');
var assets = _.transform(bundleStats.assets, function (result, statAsset) {
var bundleFilename = statAsset.name;
var asset = result[bundleFilename] = _.pick(statAsset, 'size');
// Picking modules from current bundle script
asset.modules = _(bundleStats.modules)
.filter(statModule => assetHasModule(statAsset, statModule))
.each(statModule => {
if (parsedModuleSizes) {
statModule.parsedSize = parsedModuleSizes[statModule.id];
}
});
asset.modules = _(bundleStats.modules).filter(function (statModule) {
return assetHasModule(statAsset, statModule);
}).each(function (statModule) {
if (parsedModuleSizes) {
statModule.parsedSize = parsedModuleSizes[statModule.id];
}
});

@@ -69,11 +72,11 @@ asset.tree = createModulesTree(asset.modules);

return _.transform(assets, (result, asset, filename) => {
const statSize = asset.tree.size;
const parsedSize = parsedModuleSizes ? asset.tree.parsedSize : undefined;
return _.transform(assets, function (result, asset, filename) {
var statSize = asset.tree.size;
var parsedSize = parsedModuleSizes ? asset.tree.parsedSize : undefined;
result.push({
label: filename,
weight: (parsedSize === undefined) ? statSize : parsedSize,
statSize,
parsedSize,
weight: parsedSize === undefined ? statSize : parsedSize,
statSize: statSize,
parsedSize: parsedSize,
groups: _.invokeMap(asset.tree.children, 'toChartData')

@@ -85,18 +88,16 @@ });

function readStatsFromFile(filename) {
return JSON.parse(
fs.readFileSync(filename, 'utf8')
);
return JSON.parse(fs.readFileSync(filename, 'utf8'));
}
function assetHasModule(statAsset, statModule) {
return _.some(statModule.chunks, moduleChunk =>
_.includes(statAsset.chunks, moduleChunk)
);
return _.some(statModule.chunks, function (moduleChunk) {
return _.includes(statAsset.chunks, moduleChunk);
});
}
function createModulesTree(modules) {
const root = new Folder('.');
var root = new Folder('.');
_.each(modules, module => {
const path = getModulePath(module.name);
_.each(modules, function (module) {
var path = getModulePath(module.name);
root.addFileByPath(path, module);

@@ -109,7 +110,5 @@ });

function getModulePath(path) {
return _(path)
.split('/')
.slice(1)
.map(part => (part === '~') ? 'node_modules' : part)
.value();
}
return _(path).split('/').slice(1).map(function (part) {
return part === '~' ? 'node_modules' : part;
}).value();
}

@@ -1,7 +0,24 @@

const viewer = require('./viewer');
'use strict';
class BundleAnalyzerPlugin {
var _stringify = require('babel-runtime/core-js/json/stringify');
constructor(opts) {
this.opts = Object.assign({
var _stringify2 = _interopRequireDefault(_stringify);
var _extends2 = require('babel-runtime/helpers/extends');
var _extends3 = _interopRequireDefault(_extends2);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var viewer = require('./viewer');
var BundleAnalyzerPlugin = function () {
function BundleAnalyzerPlugin(opts) {
(0, _classCallCheck3.default)(this, BundleAnalyzerPlugin);
this.opts = (0, _extends3.default)({
openAnalyzer: true,

@@ -14,29 +31,35 @@ analyzerPort: 8888,

apply(compiler) {
compiler.plugin('emit', (curCompiler, callback) => {
const stats = curCompiler
.getStats()
.toJson({
source: false,
warnings: false,
errors: false,
errorDetails: false
});
BundleAnalyzerPlugin.prototype.apply = function apply(compiler) {
var _this = this;
if (this.opts.generateStatsFile) {
const statsStr = JSON.stringify(stats, null, 2);
compiler.plugin('emit', function (curCompiler, callback) {
var stats = curCompiler.getStats().toJson({
source: false,
warnings: false,
errors: false,
errorDetails: false
});
curCompiler.assets[this.opts.statsFilename] = {
source: () => statsStr,
size: () => statsStr.length
};
if (_this.opts.generateStatsFile) {
(function () {
var statsStr = (0, _stringify2.default)(stats, null, 2);
curCompiler.assets[_this.opts.statsFilename] = {
source: function source() {
return statsStr;
},
size: function size() {
return statsStr.length;
}
};
})();
}
if (this.opts.openAnalyzer) {
if (_this.opts.openAnalyzer) {
// Making analyzer logs to be after all webpack warnings in the console
setTimeout(() => {
setTimeout(function () {
console.log('');
viewer.start(stats, {
port: this.opts.analyzerPort,
port: _this.opts.analyzerPort,
bundleDir: compiler.outputPath

@@ -49,6 +72,7 @@ });

});
}
};
}
return BundleAnalyzerPlugin;
}();
module.exports = BundleAnalyzerPlugin;
module.exports = BundleAnalyzerPlugin;
'use strict';
const fs = require('fs');
const _ = require('lodash');
const acorn = require('acorn');
const walk = require('acorn/dist/walk');
var fs = require('fs');
var _ = require('lodash');
var acorn = require('acorn');
var walk = require('acorn/dist/walk');
module.exports = {
getModuleSizesFromBundle
getModuleSizesFromBundle: getModuleSizesFromBundle
};
function getModuleSizesFromBundle(bundlePath) {
const ast = acorn.parse(
fs.readFileSync(bundlePath, 'utf8'), {
sourceType: 'script'
}
);
var ast = acorn.parse(fs.readFileSync(bundlePath, 'utf8'), {
sourceType: 'script'
});
const walkState = {
var walkState = {
sizes: null
};
walk.recursive(
ast,
walkState,
{
CallExpression: (node, state, c) => {
if (state.sizes) return;
walk.recursive(ast, walkState, {
CallExpression: function CallExpression(node, state, c) {
if (state.sizes) return;
const args = node.arguments;
var args = node.arguments;
if (_.get(node, 'callee.name') === 'webpackJsonp') {
// Additional bundle without webpack loader
// Modules are stored in second argument
state.sizes = getModulesSizesFromFunctionArgument(args[1]);
return;
}
if (_.get(node, 'callee.name') === 'webpackJsonp') {
// Additional bundle without webpack loader
// Modules are stored in second argument
state.sizes = getModulesSizesFromFunctionArgument(args[1]);
return;
}
if (
args.length === 1 &&
(args[0].type === 'ObjectExpression' || args[0].type === 'ArrayExpression')
) {
// Main bundle with webpack loader
// Modules are stored in first argument
state.sizes = getModulesSizesFromFunctionArgument(args[0]);
return;
}
if (args.length === 1 && (args[0].type === 'ObjectExpression' || args[0].type === 'ArrayExpression')) {
// Main bundle with webpack loader
// Modules are stored in first argument
state.sizes = getModulesSizesFromFunctionArgument(args[0]);
return;
}
// Continue searching
c(node, state);
}
// Continue searching
c(node, state);
}
);
});

@@ -60,6 +51,6 @@ return walkState.sizes;

if (arg.type === 'ObjectExpression') {
const modulesNodes = arg.properties;
var modulesNodes = arg.properties;
return _.transform(modulesNodes, (result, moduleNode) => {
const moduleBody = moduleNode.value.body;
return _.transform(modulesNodes, function (result, moduleNode) {
var moduleBody = moduleNode.value.body;

@@ -69,5 +60,5 @@ result[moduleNode.key.value] = moduleBody.end - moduleBody.start;

} else {
const modulesNodes = arg.elements;
var _modulesNodes = arg.elements;
return _.transform(modulesNodes, (result, moduleNode, i) => {
return _.transform(_modulesNodes, function (result, moduleNode, i) {
if (!moduleNode) return;

@@ -78,2 +69,2 @@

}
}
}
'use strict';
const _ = require('lodash');
const filesize = require('filesize');
var _create = require('babel-runtime/core-js/object/create');
class Node {
var _create2 = _interopRequireDefault(_create);
constructor(name, parent) {
var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
var _inherits2 = require('babel-runtime/helpers/inherits');
var _inherits3 = _interopRequireDefault(_inherits2);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require('babel-runtime/helpers/createClass');
var _createClass3 = _interopRequireDefault(_createClass2);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var _ = require('lodash');
var filesize = require('filesize');
var Node = function () {
function Node(name, parent) {
(0, _classCallCheck3.default)(this, Node);
this.name = name;

@@ -13,42 +36,42 @@ this.parent = parent;

get path() {
const path = [];
let node = this;
Node.prototype.toString = function toString(indent) {
indent = indent || '|';
while (node) {
path.push(node.name);
node = node.parent;
}
return indent + ' ' + this.name;
};
return path.reverse().join('/');
}
(0, _createClass3.default)(Node, [{
key: 'path',
get: function get() {
var path = [];
var node = this;
toString(indent) {
indent = indent || '|';
while (node) {
path.push(node.name);
node = node.parent;
}
return `${indent} ${this.name}`;
}
return path.reverse().join('/');
}
}]);
return Node;
}();
}
var File = function (_Node) {
(0, _inherits3.default)(File, _Node);
class File extends Node {
function File(name, data, parent) {
(0, _classCallCheck3.default)(this, File);
constructor(name, data, parent) {
super(name, parent);
this.data = data;
}
var _this = (0, _possibleConstructorReturn3.default)(this, _Node.call(this, name, parent));
get size() {
return this.data.size;
_this.data = data;
return _this;
}
get parsedSize() {
return this.data.parsedSize;
}
File.prototype.toString = function toString(indent) {
return _Node.prototype.toString.call(this, indent) + ' [' + this.data.id + '] (' + filesize(this.size) + ' / ' + filesize(this.parsedSize) + ')';
};
toString(indent) {
return `${super.toString(indent)} [${this.data.id}] (${filesize(this.size)} / ${filesize(this.parsedSize)})`;
}
toChartData() {
File.prototype.toChartData = function toChartData() {
return {

@@ -58,50 +81,40 @@ id: this.data.id,

path: this.path,
weight: (this.parsedSize === undefined) ? this.size : this.parsedSize,
weight: this.parsedSize === undefined ? this.size : this.parsedSize,
statSize: this.size,
parsedSize: this.parsedSize
};
}
};
}
class Folder extends Node {
constructor(name, parent) {
super(name, parent);
this.children = Object.create(null);
}
get size() {
if (!_.has(this, '_size')) {
this._size = this.walk((node, size) => (size + node.size), 0);
(0, _createClass3.default)(File, [{
key: 'size',
get: function get() {
return this.data.size;
}
}, {
key: 'parsedSize',
get: function get() {
return this.data.parsedSize;
}
}]);
return File;
}(Node);
return this._size;
}
var Folder = function (_Node2) {
(0, _inherits3.default)(Folder, _Node2);
get parsedSize() {
if (!_.has(this, '_parsedSize')) {
this._parsedSize = this.walk((node, size, stop) => {
if (node.parsedSize === undefined) {
return stop(undefined);
}
function Folder(name, parent) {
(0, _classCallCheck3.default)(this, Folder);
return (size + node.parsedSize);
}, 0);
}
var _this2 = (0, _possibleConstructorReturn3.default)(this, _Node2.call(this, name, parent));
/*if (this.name === 'bluebird') {
console.log(this._parsedSize);
}*/
return this._parsedSize;
_this2.children = (0, _create2.default)(null);
return _this2;
}
getChild(name) {
Folder.prototype.getChild = function getChild(name) {
return this.children[name];
}
};
addFolder(name) {
const folder = new Folder(name, this);
Folder.prototype.addFolder = function addFolder(name) {
var folder = new Folder(name, this);

@@ -113,7 +126,9 @@ this.children[name] = folder;

return folder;
}
};
addFile(name, data, overwrite = false) {
const file = new File(name, data, this);
Folder.prototype.addFile = function addFile(name, data) {
var overwrite = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
var file = new File(name, data, this);
if (this.children[name] && !overwrite) {

@@ -128,9 +143,12 @@ return this.children[name];

return file;
}
};
addFileByPath(path, data) {
const [folderNames, fileName] = [path.slice(0, -1), _.last(path)];
let currentFolder = this;
Folder.prototype.addFileByPath = function addFileByPath(path, data) {
var _ref = [path.slice(0, -1), _.last(path)];
var folderNames = _ref[0];
var fileName = _ref[1];
_.each(folderNames, folderName => {
var currentFolder = this;
_.each(folderNames, function (folderName) {
currentFolder = currentFolder.getChild(folderName) || currentFolder.addFolder(folderName);

@@ -140,8 +158,10 @@ });

currentFolder.addFile(fileName, data);
}
};
walk(walker, state = {}) {
let stopped = false;
Folder.prototype.walk = function walk(walker) {
var state = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
_.each(this.children, child => {
var stopped = false;
_.each(this.children, function (child) {
if (child.walk) {

@@ -162,24 +182,25 @@ state = child.walk(walker, state, stop);

}
}
};
toString(indent, opts) {
const { sortBy } = opts || {};
Folder.prototype.toString = function toString(indent, opts) {
var _ref2 = opts || {};
var sortBy = _ref2.sortBy;
indent = indent || '|';
let str = `${indent} ${this.name} (${filesize(this.size)} / ${filesize(this.parsedSize)})\n`;
var str = indent + ' ' + this.name + ' (' + filesize(this.size) + ' / ' + filesize(this.parsedSize) + ')\n';
str += _(this.children)
.sortBy(sortBy)
.reverse()
.map(child => child.toString(`${indent} |`, opts))
.join('\n');
str += _(this.children).sortBy(sortBy).reverse().map(function (child) {
return child.toString(indent + ' |', opts);
}).join('\n');
return str;
}
};
toChartData() {
Folder.prototype.toChartData = function toChartData() {
return {
label: this.name,
path: this.path,
weight: (this.parsedSize === undefined) ? this.size : this.parsedSize,
weight: this.parsedSize === undefined ? this.size : this.parsedSize,
statSize: this.size,

@@ -189,10 +210,42 @@ parsedSize: this.parsedSize,

};
}
};
}
(0, _createClass3.default)(Folder, [{
key: 'size',
get: function get() {
if (!_.has(this, '_size')) {
this._size = this.walk(function (node, size) {
return size + node.size;
}, 0);
}
return this._size;
}
}, {
key: 'parsedSize',
get: function get() {
if (!_.has(this, '_parsedSize')) {
this._parsedSize = this.walk(function (node, size, stop) {
if (node.parsedSize === undefined) {
return stop(undefined);
}
return size + node.parsedSize;
}, 0);
}
/*if (this.name === 'bluebird') {
console.log(this._parsedSize);
}*/
return this._parsedSize;
}
}]);
return Folder;
}(Node);
module.exports = {
Node,
File,
Folder
};
Node: Node,
File: File,
Folder: Folder
};

@@ -1,13 +0,33 @@

const express = require('express');
const opener = require('opener');
const { bold } = require('chalk');
'use strict';
const analyzer = require('./analyzer');
var _stringify = require('babel-runtime/core-js/json/stringify');
var _stringify2 = _interopRequireDefault(_stringify);
var _extends2 = require('babel-runtime/helpers/extends');
var _extends3 = _interopRequireDefault(_extends2);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var path = require('path');
var express = require('express');
var opener = require('opener');
var _require = require('chalk');
var bold = _require.bold;
var analyzer = require('./analyzer');
var projectRoot = path.resolve(__dirname, '..');
module.exports = {
start
start: start
};
function start(bundleStats, opts) {
opts = Object.assign({
opts = (0, _extends3.default)({
port: 8888,

@@ -18,30 +38,27 @@ openBrowser: true,

let chartData;
var chartData = void 0;
try {
chartData = analyzer.getChartData(bundleStats, opts.bundleDir);
} catch (err) {
console.error(`Could't analyze webpack bundle:\n${err}`);
console.error('Could\'t analyze webpack bundle:\n' + err);
return;
}
const app = express();
var app = express();
app.set('views', `${__dirname}`);
app.set('view engine', 'pug');
app.use(express.static(`${__dirname}/client`));
app.use(express.static(`${__dirname}/../node_modules`));
app.set('views', projectRoot + '/views');
app.use(express.static(projectRoot + '/client'));
app.use(express.static(projectRoot + '/node_modules'));
app.use('/', (req, res) => {
app.use('/', function (req, res) {
res.render('viewer', {
chartData: JSON.stringify(chartData)
chartData: (0, _stringify2.default)(chartData)
});
});
return app.listen(opts.port, () => {
const url = `http://localhost:${opts.port}`;
return app.listen(opts.port, function () {
var url = 'http://localhost:' + opts.port;
console.log(
`${bold('Webpack Bundle Analyzer')} is started at ${bold(url)}\n` +
`Use ${bold('Ctrl+C')} to close it`
);
console.log(bold('Webpack Bundle Analyzer') + ' is started at ' + bold(url) + '\n' + ('Use ' + bold('Ctrl+C') + ' to close it'));

@@ -52,2 +69,2 @@ if (opts.openBrowser) {

});
}
}
{
"name": "webpack-bundle-analyzer",
"version": "1.0.1-alpha",
"main": "index.js",
"bin": "bin/analyzer.js",
"version": "1.1.0-alpha",
"description": "Webpack Bundle Analyzer that represents all the information in convenient interative treemap",
"author": "Yury Grunin <grunin.ya@ya.ru>",
"license": "MIT",
"main": "lib/index.js",
"bin": "lib/bin/analyzer.js",
"engines": {
"node": ">= 0.10"
},
"scripts": {
"prepublish": "gulp build"
},
"files": [
"client",
"lib",
"src",
"views"
],
"dependencies": {
"acorn": "^4.0.3",
"babel-runtime": "^6.11.6",
"chalk": "^1.1.3",
"express": "^4.14.0",
"file-exists": "^2.0.0",
"filesize": "^3.3.0",
"lodash": "^4.16.4",
"opener": "^1.4.2",
"pug": "^2.0.0-beta6",
"stream-combiner2": "^1.1.1"
},
"devDependencies": {
"babel-core": "^6.17.0",
"babel-plugin-transform-runtime": "^6.15.0",
"babel-preset-es2015": "^6.16.0",
"babel-preset-stage-2": "^6.17.0",
"del": "^2.2.2",
"eslint": "^3.7.1",
"gulp": "^3.9.1",
"gulp-babel": "^6.1.2",
"gulp-plumber": "^1.1.0",
"gulp-util": "^3.0.7",
"gulp-watch": "^4.3.10"
},
"keywords": [
"webpack",
"bundle",
"analyzer",
"modules",
"size",
"analyzer",
"interactive",
"chart",
"treemap"
],
"author": "Yury Grunin <grunin.ya@ya.ru>",
"engines": {
"node": ">= 6"
},
"dependencies": {
"acorn": "4.0.3",
"chalk": "1.1.3",
"express": "4.14.0",
"file-exists": "2.0.0",
"filesize": "3.3.0",
"lodash": "4.16.4",
"opener": "1.4.2",
"pug": "2.0.0-beta6"
},
"devDependencies": {
"eslint": "3.7.1"
}
"treemap",
"zoomable",
"zoom"
]
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc