webpack-bundle-analyzer 2.13.1 → 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -0
- package/README.md +1 -1
- package/lib/BundleAnalyzerPlugin.js +109 -133
- package/lib/Logger.js +19 -75
- package/lib/analyzer.js +51 -77
- package/lib/bin/analyzer.js +32 -37
- package/lib/index.js +4 -3
- package/lib/parseUtils.js +50 -75
- package/lib/tree/BaseFolder.js +92 -101
- package/lib/tree/ConcatenatedModule.js +57 -90
- package/lib/tree/ContentFolder.js +29 -49
- package/lib/tree/ContentModule.js +27 -47
- package/lib/tree/Folder.js +49 -84
- package/lib/tree/Module.js +51 -77
- package/lib/tree/Node.js +18 -23
- package/lib/tree/utils.js +8 -16
- package/lib/utils.js +12 -17
- package/lib/viewer.js +96 -112
- package/package.json +47 -35
- package/public/viewer.js +40 -1
- package/public/viewer.js.map +1 -1
- package/src/BundleAnalyzerPlugin.js +2 -2
- package/src/analyzer.js +3 -2
- package/src/bin/analyzer.js +2 -2
- package/src/index.js +1 -1
- package/src/tree/BaseFolder.js +27 -1
- package/src/tree/ConcatenatedModule.js +5 -1
- package/src/tree/Folder.js +1 -1
- package/src/tree/Node.js +4 -0
- package/src/utils.js +2 -2
- package/src/viewer.js +5 -5
package/lib/bin/analyzer.js
CHANGED
|
@@ -1,60 +1,55 @@
|
|
|
1
1
|
#! /usr/bin/env node
|
|
2
|
-
|
|
2
|
+
"use strict";
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
const {
|
|
5
|
+
resolve,
|
|
6
|
+
dirname
|
|
7
|
+
} = require('path');
|
|
5
8
|
|
|
6
|
-
|
|
9
|
+
const _ = require('lodash');
|
|
7
10
|
|
|
8
|
-
|
|
9
|
-
resolve = _require.resolve,
|
|
10
|
-
dirname = _require.dirname;
|
|
11
|
+
const commander = require('commander');
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
const {
|
|
14
|
+
magenta
|
|
15
|
+
} = require('chalk');
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
magenta = _require2.magenta;
|
|
17
|
+
const analyzer = require('../analyzer');
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
var viewer = require('../viewer');
|
|
20
|
-
var Logger = require('../Logger');
|
|
19
|
+
const viewer = require('../viewer');
|
|
21
20
|
|
|
22
|
-
|
|
21
|
+
const Logger = require('../Logger');
|
|
23
22
|
|
|
24
|
-
|
|
23
|
+
const SIZES = new Set(['stat', 'parsed', 'gzip']);
|
|
24
|
+
const program = commander.version(require('../../package.json').version).usage(`<bundleStatsFile> [bundleDir] [options]
|
|
25
25
|
|
|
26
26
|
Arguments:
|
|
27
27
|
|
|
28
28
|
bundleStatsFile Path to Webpack Stats JSON file.
|
|
29
29
|
bundleDir Directory containing all generated bundles.
|
|
30
30
|
You should provided it if you want analyzer to show you the real parsed module sizes.
|
|
31
|
-
By default a directory of stats file is used.`).option('-m, --mode <mode>', 'Analyzer mode. Should be `server` or `static`.' + br('In `server` mode analyzer will start HTTP server to show bundle report.') + br('In `static` mode single HTML file with bundle report will be generated.'), 'server').option('-h, --host <host>', 'Host that will be used in `server` mode to start HTTP server.', '127.0.0.1').option('-p, --port <n>', 'Port that will be used in `server` mode to start HTTP server.', Number, 8888).option('-r, --report <file>', 'Path to bundle report file that will be generated in `static` mode.', 'report.html').option('-s, --default-sizes <type>', 'Module sizes to show in treemap by default.' + br(`Possible values: ${[].
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
var logger = new Logger(logLevel);
|
|
46
|
-
|
|
31
|
+
By default a directory of stats file is used.`).option('-m, --mode <mode>', 'Analyzer mode. Should be `server` or `static`.' + br('In `server` mode analyzer will start HTTP server to show bundle report.') + br('In `static` mode single HTML file with bundle report will be generated.'), 'server').option('-h, --host <host>', 'Host that will be used in `server` mode to start HTTP server.', '127.0.0.1').option('-p, --port <n>', 'Port that will be used in `server` mode to start HTTP server.', Number, 8888).option('-r, --report <file>', 'Path to bundle report file that will be generated in `static` mode.', 'report.html').option('-s, --default-sizes <type>', 'Module sizes to show in treemap by default.' + br(`Possible values: ${[...SIZES].join(', ')}`), 'parsed').option('-O, --no-open', "Don't open report in default browser automatically.").option('-e, --exclude <regexp>', 'Assets that should be excluded from the report.' + br('Can be specified multiple times.'), array()).option('-l, --log-level <level>', 'Log level.' + br(`Possible values: ${[...Logger.levels].join(', ')}`), Logger.defaultLevel).parse(process.argv);
|
|
32
|
+
let {
|
|
33
|
+
mode,
|
|
34
|
+
host,
|
|
35
|
+
port,
|
|
36
|
+
report: reportFilename,
|
|
37
|
+
defaultSizes,
|
|
38
|
+
logLevel,
|
|
39
|
+
open: openBrowser,
|
|
40
|
+
exclude: excludeAssets,
|
|
41
|
+
args: [bundleStatsFile, bundleDir]
|
|
42
|
+
} = program;
|
|
43
|
+
const logger = new Logger(logLevel);
|
|
47
44
|
if (!bundleStatsFile) showHelp('Provide path to Webpack Stats file as first argument');
|
|
48
45
|
if (mode !== 'server' && mode !== 'static') showHelp('Invalid mode. Should be either `server` or `static`.');
|
|
49
46
|
if (mode === 'server' && !host) showHelp('Invalid host name');
|
|
50
47
|
if (mode === 'server' && isNaN(port)) showHelp('Invalid port number');
|
|
51
|
-
if (!SIZES.has(defaultSizes)) showHelp(`Invalid default sizes option. Possible values are: ${[].
|
|
52
|
-
|
|
48
|
+
if (!SIZES.has(defaultSizes)) showHelp(`Invalid default sizes option. Possible values are: ${[...SIZES].join(', ')}`);
|
|
53
49
|
bundleStatsFile = resolve(bundleStatsFile);
|
|
54
|
-
|
|
55
50
|
if (!bundleDir) bundleDir = dirname(bundleStatsFile);
|
|
51
|
+
let bundleStats;
|
|
56
52
|
|
|
57
|
-
var bundleStats = void 0;
|
|
58
53
|
try {
|
|
59
54
|
bundleStats = analyzer.readStatsFromFile(bundleStatsFile);
|
|
60
55
|
} catch (err) {
|
|
@@ -95,8 +90,8 @@ function br(str) {
|
|
|
95
90
|
}
|
|
96
91
|
|
|
97
92
|
function array() {
|
|
98
|
-
|
|
99
|
-
return
|
|
93
|
+
const arr = [];
|
|
94
|
+
return val => {
|
|
100
95
|
arr.push(val);
|
|
101
96
|
return arr;
|
|
102
97
|
};
|
package/lib/index.js
CHANGED
package/lib/parseUtils.js
CHANGED
|
@@ -1,72 +1,67 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
|
|
5
|
+
const _ = require('lodash');
|
|
6
|
+
|
|
7
|
+
const acorn = require('acorn');
|
|
8
|
+
|
|
9
|
+
const walk = require('acorn/dist/walk');
|
|
7
10
|
|
|
8
11
|
module.exports = {
|
|
9
12
|
parseBundle
|
|
10
13
|
};
|
|
11
14
|
|
|
12
15
|
function parseBundle(bundlePath) {
|
|
13
|
-
|
|
14
|
-
|
|
16
|
+
const content = fs.readFileSync(bundlePath, 'utf8');
|
|
17
|
+
const ast = acorn.parse(content, {
|
|
15
18
|
sourceType: 'script',
|
|
16
19
|
// I believe in a bright future of ECMAScript!
|
|
17
20
|
// Actually, it's set to `2050` to support the latest ECMAScript version that currently exists.
|
|
18
21
|
// Seems like `acorn` supports such weird option value.
|
|
19
22
|
ecmaVersion: 2050
|
|
20
23
|
});
|
|
21
|
-
|
|
22
|
-
var walkState = {
|
|
24
|
+
const walkState = {
|
|
23
25
|
locations: null
|
|
24
26
|
};
|
|
25
|
-
|
|
26
27
|
walk.recursive(ast, walkState, {
|
|
27
28
|
CallExpression(node, state, c) {
|
|
28
29
|
if (state.locations) return;
|
|
29
|
-
|
|
30
|
-
var args = node.arguments;
|
|
31
|
-
|
|
32
|
-
// Main chunk with webpack loader.
|
|
30
|
+
const args = node.arguments; // Main chunk with webpack loader.
|
|
33
31
|
// Modules are stored in first argument:
|
|
34
32
|
// (function (...) {...})(<modules>)
|
|
33
|
+
|
|
35
34
|
if (node.callee.type === 'FunctionExpression' && !node.callee.id && args.length === 1 && isSimpleModulesList(args[0])) {
|
|
36
35
|
state.locations = getModulesLocations(args[0]);
|
|
37
36
|
return;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Async Webpack < v4 chunk without webpack loader.
|
|
37
|
+
} // Async Webpack < v4 chunk without webpack loader.
|
|
41
38
|
// webpackJsonp([<chunks>], <modules>, ...)
|
|
42
39
|
// As function name may be changed with `output.jsonpFunction` option we can't rely on it's default name.
|
|
40
|
+
|
|
41
|
+
|
|
43
42
|
if (node.callee.type === 'Identifier' && mayBeAsyncChunkArguments(args) && isModulesList(args[1])) {
|
|
44
43
|
state.locations = getModulesLocations(args[1]);
|
|
45
44
|
return;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Async Webpack v4 chunk without webpack loader.
|
|
45
|
+
} // Async Webpack v4 chunk without webpack loader.
|
|
49
46
|
// (window.webpackJsonp=window.webpackJsonp||[]).push([[<chunks>], <modules>, ...]);
|
|
50
47
|
// As function name may be changed with `output.jsonpFunction` option we can't rely on it's default name.
|
|
48
|
+
|
|
49
|
+
|
|
51
50
|
if (isAsyncChunkPushExpression(node)) {
|
|
52
51
|
state.locations = getModulesLocations(args[0].elements[1]);
|
|
53
52
|
return;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Walking into arguments because some of plugins (e.g. `DedupePlugin`) or some Webpack
|
|
53
|
+
} // Walking into arguments because some of plugins (e.g. `DedupePlugin`) or some Webpack
|
|
57
54
|
// features (e.g. `umd` library output) can wrap modules list into additional IIFE.
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
_.each(args, arg => c(arg, state));
|
|
61
58
|
}
|
|
62
|
-
});
|
|
63
59
|
|
|
64
|
-
|
|
60
|
+
});
|
|
61
|
+
let modules;
|
|
65
62
|
|
|
66
63
|
if (walkState.locations) {
|
|
67
|
-
modules = _.mapValues(walkState.locations,
|
|
68
|
-
return content.slice(loc.start, loc.end);
|
|
69
|
-
});
|
|
64
|
+
modules = _.mapValues(walkState.locations, loc => content.slice(loc.start, loc.end));
|
|
70
65
|
} else {
|
|
71
66
|
modules = {};
|
|
72
67
|
}
|
|
@@ -78,16 +73,13 @@ function parseBundle(bundlePath) {
|
|
|
78
73
|
}
|
|
79
74
|
|
|
80
75
|
function isModulesList(node) {
|
|
81
|
-
return isSimpleModulesList(node) ||
|
|
82
|
-
// Modules are contained in expression `Array([minimum ID]).concat([<module>, <module>, ...])`
|
|
76
|
+
return isSimpleModulesList(node) || // Modules are contained in expression `Array([minimum ID]).concat([<module>, <module>, ...])`
|
|
83
77
|
isOptimizedModulesArray(node);
|
|
84
78
|
}
|
|
85
79
|
|
|
86
80
|
function isSimpleModulesList(node) {
|
|
87
|
-
return (
|
|
88
|
-
// Modules are contained in
|
|
89
|
-
isModulesHash(node) ||
|
|
90
|
-
// Modules are contained in array. Indexes are module ids.
|
|
81
|
+
return (// Modules are contained in hash. Keys are module ids.
|
|
82
|
+
isModulesHash(node) || // Modules are contained in array. Indexes are module ids.
|
|
91
83
|
isModulesArray(node)
|
|
92
84
|
);
|
|
93
85
|
}
|
|
@@ -97,34 +89,24 @@ function isModulesHash(node) {
|
|
|
97
89
|
}
|
|
98
90
|
|
|
99
91
|
function isModulesArray(node) {
|
|
100
|
-
return node.type === 'ArrayExpression' && _.every(node.elements,
|
|
101
|
-
|
|
102
|
-
// Some of array items may be skipped because there is no module with such id
|
|
103
|
-
!elem || isModuleWrapper(elem)
|
|
104
|
-
);
|
|
105
|
-
});
|
|
92
|
+
return node.type === 'ArrayExpression' && _.every(node.elements, elem => // Some of array items may be skipped because there is no module with such id
|
|
93
|
+
!elem || isModuleWrapper(elem));
|
|
106
94
|
}
|
|
107
95
|
|
|
108
96
|
function isOptimizedModulesArray(node) {
|
|
109
97
|
// Checking whether modules are contained in `Array(<minimum ID>).concat(...modules)` array:
|
|
110
98
|
// https://github.com/webpack/webpack/blob/v1.14.0/lib/Template.js#L91
|
|
111
99
|
// The `<minimum ID>` + array indexes are module ids
|
|
112
|
-
return node.type === 'CallExpression' && node.callee.type === 'MemberExpression' &&
|
|
113
|
-
// Make sure the
|
|
114
|
-
node.callee.
|
|
115
|
-
// Make sure the property X called for `Array(<some number>).X` is `concat`
|
|
116
|
-
node.callee.property.type === 'Identifier' && node.callee.property.name === 'concat' &&
|
|
117
|
-
// Make sure exactly one array is passed in to `concat`
|
|
100
|
+
return node.type === 'CallExpression' && node.callee.type === 'MemberExpression' && // Make sure the object called is `Array(<some number>)`
|
|
101
|
+
node.callee.object.type === 'CallExpression' && node.callee.object.callee.type === 'Identifier' && node.callee.object.callee.name === 'Array' && node.callee.object.arguments.length === 1 && isNumericId(node.callee.object.arguments[0]) && // Make sure the property X called for `Array(<some number>).X` is `concat`
|
|
102
|
+
node.callee.property.type === 'Identifier' && node.callee.property.name === 'concat' && // Make sure exactly one array is passed in to `concat`
|
|
118
103
|
node.arguments.length === 1 && isModulesArray(node.arguments[0]);
|
|
119
104
|
}
|
|
120
105
|
|
|
121
106
|
function isModuleWrapper(node) {
|
|
122
|
-
return (
|
|
123
|
-
|
|
124
|
-
(node
|
|
125
|
-
// If `DedupePlugin` is used it can be an ID of duplicated module...
|
|
126
|
-
isModuleId(node) ||
|
|
127
|
-
// or an array of shape [<module_id>, ...args]
|
|
107
|
+
return (// It's an anonymous function expression that wraps module
|
|
108
|
+
(node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression') && !node.id || // If `DedupePlugin` is used it can be an ID of duplicated module...
|
|
109
|
+
isModuleId(node) || // or an array of shape [<module_id>, ...args]
|
|
128
110
|
node.type === 'ArrayExpression' && node.elements.length > 1 && isModuleId(node.elements[0])
|
|
129
111
|
);
|
|
130
112
|
}
|
|
@@ -143,12 +125,11 @@ function isChunkIds(node) {
|
|
|
143
125
|
}
|
|
144
126
|
|
|
145
127
|
function isAsyncChunkPushExpression(node) {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
return callee.type === 'MemberExpression' && callee.property.name === 'push' && callee.object.type === 'AssignmentExpression' && callee.object.left.object && (callee.object.left.object.name === 'window' ||
|
|
151
|
-
// Webpack 4 uses `this` instead of `window`
|
|
128
|
+
const {
|
|
129
|
+
callee,
|
|
130
|
+
arguments: args
|
|
131
|
+
} = node;
|
|
132
|
+
return callee.type === 'MemberExpression' && callee.property.name === 'push' && callee.object.type === 'AssignmentExpression' && callee.object.left.object && (callee.object.left.object.name === 'window' || // Webpack 4 uses `this` instead of `window`
|
|
152
133
|
callee.object.left.object.type === 'ThisExpression') && args.length === 1 && args[0].type === 'ArrayExpression' && mayBeAsyncChunkArguments(args[0].elements) && isModulesList(args[0].elements[1]);
|
|
153
134
|
}
|
|
154
135
|
|
|
@@ -159,29 +140,23 @@ function mayBeAsyncChunkArguments(args) {
|
|
|
159
140
|
function getModulesLocations(node) {
|
|
160
141
|
if (node.type === 'ObjectExpression') {
|
|
161
142
|
// Modules hash
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
var moduleId = moduleNode.key.name || moduleNode.key.value;
|
|
166
|
-
|
|
143
|
+
const modulesNodes = node.properties;
|
|
144
|
+
return _.transform(modulesNodes, (result, moduleNode) => {
|
|
145
|
+
const moduleId = moduleNode.key.name || moduleNode.key.value;
|
|
167
146
|
result[moduleId] = getModuleLocation(moduleNode.value);
|
|
168
147
|
}, {});
|
|
169
148
|
}
|
|
170
149
|
|
|
171
|
-
|
|
150
|
+
const isOptimizedArray = node.type === 'CallExpression';
|
|
172
151
|
|
|
173
152
|
if (node.type === 'ArrayExpression' || isOptimizedArray) {
|
|
174
153
|
// Modules array or optimized array
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
node.callee.object.arguments[0].value :
|
|
178
|
-
// `0` for simple array
|
|
154
|
+
const minId = isOptimizedArray ? // Get the [minId] value from the Array() call first argument literal value
|
|
155
|
+
node.callee.object.arguments[0].value : // `0` for simple array
|
|
179
156
|
0;
|
|
180
|
-
|
|
181
|
-
// The modules reside in the `concat()` function call arguments
|
|
157
|
+
const modulesNodes = isOptimizedArray ? // The modules reside in the `concat()` function call arguments
|
|
182
158
|
node.arguments[0].elements : node.elements;
|
|
183
|
-
|
|
184
|
-
return _.transform(_modulesNodes, function (result, moduleNode, i) {
|
|
159
|
+
return _.transform(modulesNodes, (result, moduleNode, i) => {
|
|
185
160
|
if (!moduleNode) return;
|
|
186
161
|
result[i + minId] = getModuleLocation(moduleNode);
|
|
187
162
|
}, {});
|
package/lib/tree/BaseFolder.js
CHANGED
|
@@ -1,138 +1,129 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
exports.default = void 0;
|
|
6
7
|
|
|
7
|
-
var
|
|
8
|
+
var _lodash = _interopRequireDefault(require("lodash"));
|
|
8
9
|
|
|
9
|
-
var
|
|
10
|
-
|
|
11
|
-
var _lodash2 = _interopRequireDefault(_lodash);
|
|
12
|
-
|
|
13
|
-
var _Node2 = require('./Node');
|
|
14
|
-
|
|
15
|
-
var _Node3 = _interopRequireDefault(_Node2);
|
|
10
|
+
var _Node = _interopRequireDefault(require("./Node"));
|
|
16
11
|
|
|
17
12
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
18
13
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
14
|
+
class BaseFolder extends _Node.default {
|
|
15
|
+
constructor(name, parent) {
|
|
16
|
+
super(name, parent);
|
|
17
|
+
this.children = Object.create(null);
|
|
18
|
+
}
|
|
22
19
|
|
|
23
|
-
|
|
20
|
+
get src() {
|
|
21
|
+
if (!_lodash.default.has(this, '_src')) {
|
|
22
|
+
this._src = this.walk((node, src) => src += node.src || '', '', false);
|
|
23
|
+
}
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
return this._src;
|
|
26
|
+
}
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
get size() {
|
|
29
|
+
if (!_lodash.default.has(this, '_size')) {
|
|
30
|
+
this._size = this.walk((node, size) => size + node.size, 0, false);
|
|
31
|
+
}
|
|
30
32
|
|
|
31
|
-
|
|
33
|
+
return this._size;
|
|
34
|
+
}
|
|
32
35
|
|
|
33
|
-
|
|
34
|
-
return
|
|
36
|
+
getChild(name) {
|
|
37
|
+
return this.children[name];
|
|
35
38
|
}
|
|
36
39
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
addChildModule(module) {
|
|
41
|
+
const {
|
|
42
|
+
name
|
|
43
|
+
} = module;
|
|
44
|
+
const currentChild = this.children[name]; // For some reason we already have this node in children and it's a folder.
|
|
45
|
+
|
|
46
|
+
if (currentChild && currentChild instanceof BaseFolder) return;
|
|
47
|
+
|
|
48
|
+
if (currentChild) {
|
|
49
|
+
// We already have this node in children and it's a module.
|
|
50
|
+
// Merging it's data.
|
|
51
|
+
currentChild.mergeData(module.data);
|
|
52
|
+
} else {
|
|
53
|
+
// Pushing new module
|
|
54
|
+
module.parent = this;
|
|
55
|
+
this.children[name] = module;
|
|
41
56
|
}
|
|
42
|
-
}, {
|
|
43
|
-
key: 'addChildModule',
|
|
44
|
-
value: function addChildModule(module) {
|
|
45
|
-
var name = module.name;
|
|
46
57
|
|
|
47
|
-
|
|
58
|
+
delete this._size;
|
|
59
|
+
delete this._src;
|
|
60
|
+
}
|
|
48
61
|
|
|
49
|
-
|
|
50
|
-
|
|
62
|
+
addChildFolder(folder) {
|
|
63
|
+
folder.parent = this;
|
|
64
|
+
this.children[folder.name] = folder;
|
|
65
|
+
delete this._size;
|
|
66
|
+
delete this._src;
|
|
67
|
+
return folder;
|
|
68
|
+
}
|
|
51
69
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
70
|
+
walk(walker, state = {}, deep = true) {
|
|
71
|
+
let stopped = false;
|
|
72
|
+
|
|
73
|
+
_lodash.default.each(this.children, child => {
|
|
74
|
+
if (deep && child.walk) {
|
|
75
|
+
state = child.walk(walker, state, stop);
|
|
56
76
|
} else {
|
|
57
|
-
|
|
58
|
-
module.parent = this;
|
|
59
|
-
this.children[name] = module;
|
|
77
|
+
state = walker(child, state, stop);
|
|
60
78
|
}
|
|
61
79
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
65
|
-
}, {
|
|
66
|
-
key: 'addChildFolder',
|
|
67
|
-
value: function addChildFolder(folder) {
|
|
68
|
-
folder.parent = this;
|
|
69
|
-
this.children[folder.name] = folder;
|
|
70
|
-
delete this._size;
|
|
71
|
-
delete this._src;
|
|
72
|
-
|
|
73
|
-
return folder;
|
|
74
|
-
}
|
|
75
|
-
}, {
|
|
76
|
-
key: 'walk',
|
|
77
|
-
value: function walk(walker) {
|
|
78
|
-
var state = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
79
|
-
var deep = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
|
|
80
|
+
if (stopped) return false;
|
|
81
|
+
});
|
|
80
82
|
|
|
81
|
-
|
|
83
|
+
return state;
|
|
82
84
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
85
|
+
function stop(finalState) {
|
|
86
|
+
stopped = true;
|
|
87
|
+
return finalState;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
89
90
|
|
|
90
|
-
|
|
91
|
-
|
|
91
|
+
mergeNestedFolders() {
|
|
92
|
+
if (!this.isRoot) {
|
|
93
|
+
let childNames;
|
|
92
94
|
|
|
93
|
-
|
|
95
|
+
while ((childNames = Object.keys(this.children)).length === 1) {
|
|
96
|
+
const childName = childNames[0];
|
|
97
|
+
const onlyChild = this.children[childName];
|
|
94
98
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
99
|
+
if (onlyChild instanceof this.constructor) {
|
|
100
|
+
this.name += `/${onlyChild.name}`;
|
|
101
|
+
this.children = onlyChild.children;
|
|
102
|
+
} else {
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
98
105
|
}
|
|
99
106
|
}
|
|
100
|
-
}, {
|
|
101
|
-
key: 'toChartData',
|
|
102
|
-
value: function toChartData() {
|
|
103
|
-
return {
|
|
104
|
-
label: this.name,
|
|
105
|
-
path: this.path,
|
|
106
|
-
statSize: this.size,
|
|
107
|
-
groups: _lodash2.default.invokeMap(this.children, 'toChartData')
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
}, {
|
|
111
|
-
key: 'src',
|
|
112
|
-
get: function get() {
|
|
113
|
-
if (!_lodash2.default.has(this, '_src')) {
|
|
114
|
-
this._src = this.walk(function (node, src) {
|
|
115
|
-
return src += node.src || '';
|
|
116
|
-
}, '', false);
|
|
117
|
-
}
|
|
118
107
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
if (!_lodash2.default.has(this, '_size')) {
|
|
125
|
-
this._size = this.walk(function (node, size) {
|
|
126
|
-
return size + node.size;
|
|
127
|
-
}, 0, false);
|
|
108
|
+
this.walk(child => {
|
|
109
|
+
child.parent = this;
|
|
110
|
+
|
|
111
|
+
if (child.mergeNestedFolders) {
|
|
112
|
+
child.mergeNestedFolders();
|
|
128
113
|
}
|
|
114
|
+
}, null, false);
|
|
115
|
+
}
|
|
129
116
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
117
|
+
toChartData() {
|
|
118
|
+
return {
|
|
119
|
+
label: this.name,
|
|
120
|
+
path: this.path,
|
|
121
|
+
statSize: this.size,
|
|
122
|
+
groups: _lodash.default.invokeMap(this.children, 'toChartData')
|
|
123
|
+
};
|
|
124
|
+
}
|
|
133
125
|
|
|
134
|
-
|
|
135
|
-
}(_Node3.default);
|
|
126
|
+
}
|
|
136
127
|
|
|
137
128
|
exports.default = BaseFolder;
|
|
138
129
|
;
|