webpack-bundle-analyzer 3.9.0 → 4.2.0
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 +29 -0
- package/lib/BundleAnalyzerPlugin.js +55 -85
- package/lib/analyzer.js +78 -35
- package/lib/bin/analyzer.js +1 -3
- package/lib/parseUtils.js +83 -10
- package/lib/statsUtils.js +90 -0
- package/lib/template.js +73 -0
- package/lib/tree/BaseFolder.js +1 -3
- package/lib/tree/ConcatenatedModule.js +4 -12
- package/lib/tree/ContentFolder.js +2 -8
- package/lib/tree/ContentModule.js +2 -8
- package/lib/tree/Folder.js +3 -11
- package/lib/utils.js +19 -4
- package/lib/viewer.js +121 -184
- package/package.json +47 -49
- package/public/viewer.js +4 -14
- package/public/viewer.js.LICENSE.txt +5 -0
- package/public/viewer.js.map +1 -1
- package/src/BundleAnalyzerPlugin.js +4 -11
- package/src/analyzer.js +76 -31
- package/src/bin/analyzer.js +1 -2
- package/src/parseUtils.js +96 -11
- package/src/statsUtils.js +82 -0
- package/{views/viewer.ejs → src/template.js} +50 -7
- package/src/tree/BaseFolder.js +1 -1
- package/src/tree/ConcatenatedModule.js +2 -2
- package/src/tree/Folder.js +1 -1
- package/src/utils.js +16 -4
- package/src/viewer.js +27 -73
- package/views/script.ejs +0 -8
package/lib/template.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/* eslint-disable max-len */
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
|
|
8
|
+
const _ = require('lodash');
|
|
9
|
+
|
|
10
|
+
const projectRoot = path.resolve(__dirname, '..');
|
|
11
|
+
const assetsRoot = path.join(projectRoot, 'public');
|
|
12
|
+
exports.renderViewer = renderViewer;
|
|
13
|
+
/**
|
|
14
|
+
* Escapes `<` characters in JSON to safely use it in `<script>` tag.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
function escapeJson(json) {
|
|
18
|
+
return JSON.stringify(json).replace(/</gu, '\\u003c');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function getAssetContent(filename) {
|
|
22
|
+
const assetPath = path.join(assetsRoot, filename);
|
|
23
|
+
|
|
24
|
+
if (!assetPath.startsWith(assetsRoot)) {
|
|
25
|
+
throw new Error(`"${filename}" is outside of the assets root`);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return fs.readFileSync(assetPath, 'utf8');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function html(strings, ...values) {
|
|
32
|
+
return strings.map((string, index) => `${string}${values[index] || ''}`).join('');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function getScript(filename, mode) {
|
|
36
|
+
if (mode === 'static') {
|
|
37
|
+
return `<!-- ${_.escape(filename)} -->
|
|
38
|
+
<script>${getAssetContent(filename)}</script>`;
|
|
39
|
+
} else {
|
|
40
|
+
return `<script src="${_.escape(filename)}"></script>`;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function renderViewer({
|
|
45
|
+
title,
|
|
46
|
+
enableWebSocket,
|
|
47
|
+
chartData,
|
|
48
|
+
defaultSizes,
|
|
49
|
+
mode
|
|
50
|
+
} = {}) {
|
|
51
|
+
return html`<!DOCTYPE html>
|
|
52
|
+
<html>
|
|
53
|
+
<head>
|
|
54
|
+
<meta charset="UTF-8"/>
|
|
55
|
+
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
|
56
|
+
<title>${_.escape(title)}</title>
|
|
57
|
+
<link rel="shortcut icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAABrVBMVEUAAAD///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+O1foceMD///+J0/qK1Pr7/v8Xdr/9///W8P4UdL7L7P0Scr2r4Pyj3vwad8D5/f/2/f+55f3E6f34+/2H0/ojfMKpzOd0rNgQcb3F3O/j9f7c8v6g3Pz0/P/w+v/q+P7n9v6T1/uQ1vuE0vqLut/y+v+Z2fvt+f+15Pzv9fuc2/vR7v2V2Pvd6/bg9P7I6/285/2y4/yp3/zp8vk8i8kqgMT7/P31+fyv4vxGkcz6/P6/6P3j7vfS5PNnpNUxhcbO7f7F6v3O4vHK3/DA2u631Ouy0eqXweKJud5wqthfoNMMbLvY8f73+v2dxeR8sNtTmdDx9/zX6PSjyeaCtd1YnNGX2PuQveCGt95Nls42h8dLlM3F4vBtAAAAM3RSTlMAAyOx0/sKBvik8opWGBMOAe3l1snDm2E9LSb06eHcu5JpHbarfHZCN9CBb08zzkdNS0kYaptYAAAFV0lEQVRYw92X51/aYBDHHS2O2qqttVbrqNq9m+TJIAYIShBkWwqIiCgoWvfeq7Z2/s29hyQNyUcR7LveGwVyXy6XH8/9rqxglLfUPLxVduUor3h0rfp2TYvpivk37929TkG037hffoX0+peVtZQc1589rigVUdXS/ABSAyEmGIO/1XfvldSK8vs3OqB6u3m0nxmIrvgB0dj7rr7Y9IbuF68hnfFaiHA/sxqm0wciIG43P60qKv9WXWc1RXGh/mFESFABTSBi0sNAKzqet17eCtOb3kZIDwxEEU0oAIJGYxNBDhBND29e0rtXXbcpuPmED9IhEAAQ/AXEaF8EPmnrrKsv0LvWR3fg5sWDNAFZOgAgaKvZDogHNU9MFwnnYROkc56RD5CjAbQX9Ow4g7upCsvYu55aSI/Nj0H1akgKQEUM94dwK65hYRmFU9MIcH/fqJYOZYcnuJSU/waKDgTOEVaVKhwrTRP5XzgSpAITYzom7UvkhFX5VutmxeNnWDjjswTKTyfgluNDGbUpWissXhF3s7mlSml+czWkg3D0l1nNjGNjz3myOQOa1KM/jOS6ebdbAVTCi4gljHSFrviza7tOgRWcS0MOUX9zdNgag5w7rRqA44Lzw0hr1WqES36dFliSJFlh2rXIae3FFcDDgKdxrUIDePr8jGcSClV1u7A9xeN0ModY/pHMxmR1EzRh8TJiwqsHmKW0l4FCEZI+jHio+JdPPE9qwQtTRxku2D8sIeRL2LnxWSllANCQGOIiqVHAz2ye2JR0DcH+HoxDkaADLjgxjKQ+AwCX/g0+DNgdG0ukYCONAe+dbc2IAc6fwt1ARoDSezNHxV2Cmzwv3O6lDMV55edBGwGK9n1+x2F8EDfAGCxug8MhpsMEcTEAWf3rx2vZhe/LAmtIn/6apE6PN0ULKgywD9mmdxbmFl3OvD5AS5fW5zLbv/YHmcsBTjf/afDz3MaZTVCfAP9z6/Bw6ycv8EUBWJIn9zYcoAWWlW9+OzO3vkTy8H+RANLmdrpOuYWdZYEXpo+TlCJrW5EARb7fF+bWdqf3hhyZI1nWJQHgznErZhbjoEsWqi8dQNoE294aldzFurwSABL2XXMf9+H1VQGke9exw5P/AnA5Pv5ngMul7LOvO922iwACu8WkCwLCafvM4CeWPxfA8lNHcWZSoi8EwMAIciKX2Z4SWCMAa3snCZ/G4EA8D6CMLNFsGQhkkz/gQNEBbPCbWsxGUpYVu3z8IyNAknwJkfPMEhLyrdi5RTyUVACkw4GSFRNWJNEW+fgPGwHD8/JxnRuLabN4CGNRkAE23na2+VmEAUmrYymSGjMAYqH84YUIyzgzs3XC7gNgH36Vcc4zKY9o9fgPBXUAiHHwVboBHGLiX6Zcjp1f2wu4tvzZKo0ecPnDtQYDQvJXaBeNzce45Fp28ZQLrEZVuFqgBwOalArKXnW1UzlnSusQKJqKYNuz4tOnI6sZG4zanpemv+7ySU2jbA9h6uhcgpfy6G2PahirDZ6zvq6zDduMVFTKvzw8wgyEdelwY9in3XkEPs3osJuwRQ4qTkfzifndg9Gfc4pdsu82+tTnHZTBa2EAMrqr2t43pguc8tNm7JQVQ2S0ukj2d22dhXYP0/veWtwKrCkNoNimAN5+Xr/oLrxswKbVJjteWrX7eR63o4j9q0GxnaBdWgGA5VStpanIjQmEhV0/nVt5VOFUvix6awJhPcAaTEShgrG+iGyvb5a0Ndb1YGHFPEwoqAinoaykaID1o1pdPNu7XsnCKQ3R+hwWIIhGvORcJUBYXe3Xa3vq/mF/N9V13ugufMkfXn+KHsRD0B8AAAAASUVORK5CYII=" type="image/x-icon" />
|
|
58
|
+
|
|
59
|
+
<script>
|
|
60
|
+
window.enableWebSocket = ${escapeJson(enableWebSocket)};
|
|
61
|
+
</script>
|
|
62
|
+
${getScript('viewer.js', mode)}
|
|
63
|
+
</head>
|
|
64
|
+
|
|
65
|
+
<body>
|
|
66
|
+
<div id="app"></div>
|
|
67
|
+
<script>
|
|
68
|
+
window.chartData = ${escapeJson(chartData)};
|
|
69
|
+
window.defaultSizes = ${escapeJson(defaultSizes)};
|
|
70
|
+
</script>
|
|
71
|
+
</body>
|
|
72
|
+
</html>`;
|
|
73
|
+
}
|
package/lib/tree/BaseFolder.js
CHANGED
|
@@ -69,8 +69,7 @@ class BaseFolder extends _Node.default {
|
|
|
69
69
|
|
|
70
70
|
walk(walker, state = {}, deep = true) {
|
|
71
71
|
let stopped = false;
|
|
72
|
-
|
|
73
|
-
_lodash.default.each(this.children, child => {
|
|
72
|
+
Object.values(this.children).forEach(child => {
|
|
74
73
|
if (deep && child.walk) {
|
|
75
74
|
state = child.walk(walker, state, stop);
|
|
76
75
|
} else {
|
|
@@ -79,7 +78,6 @@ class BaseFolder extends _Node.default {
|
|
|
79
78
|
|
|
80
79
|
if (stopped) return false;
|
|
81
80
|
});
|
|
82
|
-
|
|
83
81
|
return state;
|
|
84
82
|
|
|
85
83
|
function stop(finalState) {
|
|
@@ -17,12 +17,6 @@ var _utils = require("./utils");
|
|
|
17
17
|
|
|
18
18
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
19
19
|
|
|
20
|
-
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
|
|
21
|
-
|
|
22
|
-
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
|
23
|
-
|
|
24
|
-
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
25
|
-
|
|
26
20
|
class ConcatenatedModule extends _Module.default {
|
|
27
21
|
constructor(name, data, parent) {
|
|
28
22
|
super(name, data, parent);
|
|
@@ -32,7 +26,7 @@ class ConcatenatedModule extends _Module.default {
|
|
|
32
26
|
}
|
|
33
27
|
|
|
34
28
|
fillContentModules() {
|
|
35
|
-
|
|
29
|
+
this.data.modules.forEach(moduleData => this.addContentModule(moduleData));
|
|
36
30
|
}
|
|
37
31
|
|
|
38
32
|
addContentModule(moduleData) {
|
|
@@ -44,8 +38,7 @@ class ConcatenatedModule extends _Module.default {
|
|
|
44
38
|
|
|
45
39
|
const [folders, fileName] = [pathParts.slice(0, -1), _lodash.default.last(pathParts)];
|
|
46
40
|
let currentFolder = this;
|
|
47
|
-
|
|
48
|
-
_lodash.default.each(folders, folderName => {
|
|
41
|
+
folders.forEach(folderName => {
|
|
49
42
|
let childFolder = currentFolder.getChild(folderName);
|
|
50
43
|
|
|
51
44
|
if (!childFolder) {
|
|
@@ -54,7 +47,6 @@ class ConcatenatedModule extends _Module.default {
|
|
|
54
47
|
|
|
55
48
|
currentFolder = childFolder;
|
|
56
49
|
});
|
|
57
|
-
|
|
58
50
|
const module = new _ContentModule.default(fileName, moduleData, this);
|
|
59
51
|
currentFolder.addChildModule(module);
|
|
60
52
|
}
|
|
@@ -79,10 +71,10 @@ class ConcatenatedModule extends _Module.default {
|
|
|
79
71
|
}
|
|
80
72
|
|
|
81
73
|
toChartData() {
|
|
82
|
-
return
|
|
74
|
+
return { ...super.toChartData(),
|
|
83
75
|
concatenated: true,
|
|
84
76
|
groups: _lodash.default.invokeMap(this.children, 'toChartData')
|
|
85
|
-
}
|
|
77
|
+
};
|
|
86
78
|
}
|
|
87
79
|
|
|
88
80
|
}
|
|
@@ -9,12 +9,6 @@ var _BaseFolder = _interopRequireDefault(require("./BaseFolder"));
|
|
|
9
9
|
|
|
10
10
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
11
11
|
|
|
12
|
-
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
|
|
13
|
-
|
|
14
|
-
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
|
15
|
-
|
|
16
|
-
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
17
|
-
|
|
18
12
|
class ContentFolder extends _BaseFolder.default {
|
|
19
13
|
constructor(name, ownerModule, parent) {
|
|
20
14
|
super(name, parent);
|
|
@@ -38,11 +32,11 @@ class ContentFolder extends _BaseFolder.default {
|
|
|
38
32
|
}
|
|
39
33
|
|
|
40
34
|
toChartData() {
|
|
41
|
-
return
|
|
35
|
+
return { ...super.toChartData(),
|
|
42
36
|
parsedSize: this.parsedSize,
|
|
43
37
|
gzipSize: this.gzipSize,
|
|
44
38
|
inaccurateSizes: true
|
|
45
|
-
}
|
|
39
|
+
};
|
|
46
40
|
}
|
|
47
41
|
|
|
48
42
|
}
|
|
@@ -9,12 +9,6 @@ var _Module = _interopRequireDefault(require("./Module"));
|
|
|
9
9
|
|
|
10
10
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
11
11
|
|
|
12
|
-
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
|
|
13
|
-
|
|
14
|
-
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
|
15
|
-
|
|
16
|
-
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
17
|
-
|
|
18
12
|
class ContentModule extends _Module.default {
|
|
19
13
|
constructor(name, data, ownerModule, parent) {
|
|
20
14
|
super(name, data, parent);
|
|
@@ -38,9 +32,9 @@ class ContentModule extends _Module.default {
|
|
|
38
32
|
}
|
|
39
33
|
|
|
40
34
|
toChartData() {
|
|
41
|
-
return
|
|
35
|
+
return { ...super.toChartData(),
|
|
42
36
|
inaccurateSizes: true
|
|
43
|
-
}
|
|
37
|
+
};
|
|
44
38
|
}
|
|
45
39
|
|
|
46
40
|
}
|
package/lib/tree/Folder.js
CHANGED
|
@@ -19,12 +19,6 @@ var _utils = require("./utils");
|
|
|
19
19
|
|
|
20
20
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
21
21
|
|
|
22
|
-
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
|
|
23
|
-
|
|
24
|
-
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
|
25
|
-
|
|
26
|
-
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
27
|
-
|
|
28
22
|
class Folder extends _BaseFolder.default {
|
|
29
23
|
get parsedSize() {
|
|
30
24
|
return this.src ? this.src.length : 0;
|
|
@@ -47,8 +41,7 @@ class Folder extends _BaseFolder.default {
|
|
|
47
41
|
|
|
48
42
|
const [folders, fileName] = [pathParts.slice(0, -1), _lodash.default.last(pathParts)];
|
|
49
43
|
let currentFolder = this;
|
|
50
|
-
|
|
51
|
-
_lodash.default.each(folders, folderName => {
|
|
44
|
+
folders.forEach(folderName => {
|
|
52
45
|
let childNode = currentFolder.getChild(folderName);
|
|
53
46
|
|
|
54
47
|
if ( // Folder is not created yet
|
|
@@ -62,17 +55,16 @@ class Folder extends _BaseFolder.default {
|
|
|
62
55
|
|
|
63
56
|
currentFolder = childNode;
|
|
64
57
|
});
|
|
65
|
-
|
|
66
58
|
const ModuleConstructor = moduleData.modules ? _ConcatenatedModule.default : _Module.default;
|
|
67
59
|
const module = new ModuleConstructor(fileName, moduleData, this);
|
|
68
60
|
currentFolder.addChildModule(module);
|
|
69
61
|
}
|
|
70
62
|
|
|
71
63
|
toChartData() {
|
|
72
|
-
return
|
|
64
|
+
return { ...super.toChartData(),
|
|
73
65
|
parsedSize: this.parsedSize,
|
|
74
66
|
gzipSize: this.gzipSize
|
|
75
|
-
}
|
|
67
|
+
};
|
|
76
68
|
}
|
|
77
69
|
|
|
78
70
|
}
|
package/lib/utils.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
const {
|
|
4
|
-
inspect
|
|
4
|
+
inspect,
|
|
5
|
+
types
|
|
5
6
|
} = require('util');
|
|
6
7
|
|
|
7
8
|
const _ = require('lodash');
|
|
8
9
|
|
|
10
|
+
const opener = require('opener');
|
|
11
|
+
|
|
9
12
|
const MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
10
13
|
exports.createAssetsFilter = createAssetsFilter;
|
|
11
14
|
|
|
@@ -15,11 +18,11 @@ function createAssetsFilter(excludePatterns) {
|
|
|
15
18
|
pattern = new RegExp(pattern, 'u');
|
|
16
19
|
}
|
|
17
20
|
|
|
18
|
-
if (
|
|
21
|
+
if (types.isRegExp(pattern)) {
|
|
19
22
|
return asset => pattern.test(asset);
|
|
20
23
|
}
|
|
21
24
|
|
|
22
|
-
if (
|
|
25
|
+
if (typeof pattern !== 'function') {
|
|
23
26
|
throw new TypeError(`Pattern should be either string, RegExp or a function, but "${inspect(pattern, {
|
|
24
27
|
depth: 0
|
|
25
28
|
})}" got.`);
|
|
@@ -29,7 +32,7 @@ function createAssetsFilter(excludePatterns) {
|
|
|
29
32
|
}).value();
|
|
30
33
|
|
|
31
34
|
if (excludeFunctions.length) {
|
|
32
|
-
return asset =>
|
|
35
|
+
return asset => excludeFunctions.every(fn => fn(asset) !== true);
|
|
33
36
|
} else {
|
|
34
37
|
return () => true;
|
|
35
38
|
}
|
|
@@ -49,4 +52,16 @@ exports.defaultTitle = function () {
|
|
|
49
52
|
const minute = `0${time.getMinutes()}`.slice(-2);
|
|
50
53
|
const currentTime = `${day} ${month} ${year} at ${hour}:${minute}`;
|
|
51
54
|
return `${process.env.npm_package_name || 'Webpack Bundle Analyzer'} [${currentTime}]`;
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Calls opener on a URI, but silently try / catches it.
|
|
58
|
+
*/
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
exports.open = function (uri, logger) {
|
|
62
|
+
try {
|
|
63
|
+
opener(uri);
|
|
64
|
+
} catch (err) {
|
|
65
|
+
logger.debug(`Opener failed to open "${uri}":\n${err}`);
|
|
66
|
+
}
|
|
52
67
|
};
|
package/lib/viewer.js
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
|
|
4
|
-
|
|
5
|
-
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
|
|
6
|
-
|
|
7
3
|
const path = require('path');
|
|
8
4
|
|
|
9
5
|
const fs = require('fs');
|
|
@@ -16,12 +12,6 @@ const _ = require('lodash');
|
|
|
16
12
|
|
|
17
13
|
const express = require('express');
|
|
18
14
|
|
|
19
|
-
const ejs = require('ejs');
|
|
20
|
-
|
|
21
|
-
const opener = require('opener');
|
|
22
|
-
|
|
23
|
-
const mkdir = require('mkdirp');
|
|
24
|
-
|
|
25
15
|
const {
|
|
26
16
|
bold
|
|
27
17
|
} = require('chalk');
|
|
@@ -30,8 +20,15 @@ const Logger = require('./Logger');
|
|
|
30
20
|
|
|
31
21
|
const analyzer = require('./analyzer');
|
|
32
22
|
|
|
23
|
+
const {
|
|
24
|
+
open
|
|
25
|
+
} = require('./utils');
|
|
26
|
+
|
|
27
|
+
const {
|
|
28
|
+
renderViewer
|
|
29
|
+
} = require('./template');
|
|
30
|
+
|
|
33
31
|
const projectRoot = path.resolve(__dirname, '..');
|
|
34
|
-
const assetsRoot = path.join(projectRoot, 'public');
|
|
35
32
|
|
|
36
33
|
function resolveTitle(reportTitle) {
|
|
37
34
|
if (typeof reportTitle === 'function') {
|
|
@@ -49,192 +46,132 @@ module.exports = {
|
|
|
49
46
|
start: startServer
|
|
50
47
|
};
|
|
51
48
|
|
|
52
|
-
function startServer(
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
const app = express(); // Explicitly using our `ejs` dependency to render templates
|
|
75
|
-
// Fixes #17
|
|
76
|
-
|
|
77
|
-
app.engine('ejs', require('ejs').renderFile);
|
|
78
|
-
app.set('view engine', 'ejs');
|
|
79
|
-
app.set('views', `${projectRoot}/views`);
|
|
80
|
-
app.use(express.static(`${projectRoot}/public`));
|
|
81
|
-
app.use('/', (req, res) => {
|
|
82
|
-
res.render('viewer', {
|
|
83
|
-
mode: 'server',
|
|
84
|
-
title: resolveTitle(reportTitle),
|
|
85
|
-
|
|
86
|
-
get chartData() {
|
|
87
|
-
return chartData;
|
|
88
|
-
},
|
|
89
|
-
|
|
90
|
-
defaultSizes,
|
|
91
|
-
enableWebSocket: true,
|
|
92
|
-
// Helpers
|
|
93
|
-
escapeJson
|
|
94
|
-
});
|
|
95
|
-
});
|
|
96
|
-
const server = http.createServer(app);
|
|
97
|
-
yield new Promise(resolve => {
|
|
98
|
-
server.listen(port, host, () => {
|
|
99
|
-
resolve();
|
|
100
|
-
const url = `http://${host}:${server.address().port}`;
|
|
101
|
-
logger.info(`${bold('Webpack Bundle Analyzer')} is started at ${bold(url)}\n` + `Use ${bold('Ctrl+C')} to close it`);
|
|
102
|
-
|
|
103
|
-
if (openBrowser) {
|
|
104
|
-
opener(url);
|
|
105
|
-
}
|
|
106
|
-
});
|
|
49
|
+
async function startServer(bundleStats, opts) {
|
|
50
|
+
const {
|
|
51
|
+
port = 8888,
|
|
52
|
+
host = '127.0.0.1',
|
|
53
|
+
openBrowser = true,
|
|
54
|
+
bundleDir = null,
|
|
55
|
+
logger = new Logger(),
|
|
56
|
+
defaultSizes = 'parsed',
|
|
57
|
+
excludeAssets = null,
|
|
58
|
+
reportTitle
|
|
59
|
+
} = opts || {};
|
|
60
|
+
const analyzerOpts = {
|
|
61
|
+
logger,
|
|
62
|
+
excludeAssets
|
|
63
|
+
};
|
|
64
|
+
let chartData = getChartData(analyzerOpts, bundleStats, bundleDir);
|
|
65
|
+
if (!chartData) return;
|
|
66
|
+
const app = express();
|
|
67
|
+
app.use(express.static(`${projectRoot}/public`));
|
|
68
|
+
app.get('/', (req, res) => {
|
|
69
|
+
res.writeHead(200, {
|
|
70
|
+
'Content-Type': 'text/html'
|
|
107
71
|
});
|
|
108
|
-
const
|
|
109
|
-
server
|
|
72
|
+
const html = renderViewer({
|
|
73
|
+
mode: 'server',
|
|
74
|
+
title: resolveTitle(reportTitle),
|
|
75
|
+
chartData,
|
|
76
|
+
defaultSizes,
|
|
77
|
+
enableWebSocket: true
|
|
110
78
|
});
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
79
|
+
return res.end(html);
|
|
80
|
+
});
|
|
81
|
+
const server = http.createServer(app);
|
|
82
|
+
await new Promise(resolve => {
|
|
83
|
+
server.listen(port, host, () => {
|
|
84
|
+
resolve();
|
|
85
|
+
const url = `http://${host}:${server.address().port}`;
|
|
86
|
+
logger.info(`${bold('Webpack Bundle Analyzer')} is started at ${bold(url)}\n` + `Use ${bold('Ctrl+C')} to close it`);
|
|
87
|
+
|
|
88
|
+
if (openBrowser) {
|
|
89
|
+
open(url, logger);
|
|
90
|
+
}
|
|
117
91
|
});
|
|
118
|
-
return {
|
|
119
|
-
ws: wss,
|
|
120
|
-
http: server,
|
|
121
|
-
updateChartData
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
function updateChartData(bundleStats) {
|
|
125
|
-
const newChartData = getChartData(analyzerOpts, bundleStats, bundleDir);
|
|
126
|
-
if (!newChartData) return;
|
|
127
|
-
chartData = newChartData;
|
|
128
|
-
wss.clients.forEach(client => {
|
|
129
|
-
if (client.readyState === WebSocket.OPEN) {
|
|
130
|
-
client.send(JSON.stringify({
|
|
131
|
-
event: 'chartDataUpdated',
|
|
132
|
-
data: newChartData
|
|
133
|
-
}));
|
|
134
|
-
}
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
92
|
});
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
_generateReport = _asyncToGenerator(function* (bundleStats, opts) {
|
|
147
|
-
const {
|
|
148
|
-
openBrowser = true,
|
|
149
|
-
reportFilename,
|
|
150
|
-
reportTitle,
|
|
151
|
-
bundleDir = null,
|
|
152
|
-
logger = new Logger(),
|
|
153
|
-
defaultSizes = 'parsed',
|
|
154
|
-
excludeAssets = null
|
|
155
|
-
} = opts || {};
|
|
156
|
-
const chartData = getChartData({
|
|
157
|
-
logger,
|
|
158
|
-
excludeAssets
|
|
159
|
-
}, bundleStats, bundleDir);
|
|
160
|
-
if (!chartData) return;
|
|
161
|
-
yield new Promise((resolve, reject) => {
|
|
162
|
-
ejs.renderFile(`${projectRoot}/views/viewer.ejs`, {
|
|
163
|
-
mode: 'static',
|
|
164
|
-
title: resolveTitle(reportTitle),
|
|
165
|
-
chartData,
|
|
166
|
-
defaultSizes,
|
|
167
|
-
enableWebSocket: false,
|
|
168
|
-
// Helpers
|
|
169
|
-
assetContent: getAssetContent,
|
|
170
|
-
escapeJson
|
|
171
|
-
}, (err, reportHtml) => {
|
|
172
|
-
try {
|
|
173
|
-
if (err) {
|
|
174
|
-
logger.error(err);
|
|
175
|
-
reject(err);
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
const reportFilepath = path.resolve(bundleDir || process.cwd(), reportFilename);
|
|
180
|
-
mkdir.sync(path.dirname(reportFilepath));
|
|
181
|
-
fs.writeFileSync(reportFilepath, reportHtml);
|
|
182
|
-
logger.info(`${bold('Webpack Bundle Analyzer')} saved report to ${bold(reportFilepath)}`);
|
|
183
|
-
|
|
184
|
-
if (openBrowser) {
|
|
185
|
-
opener(`file://${reportFilepath}`);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
resolve();
|
|
189
|
-
} catch (e) {
|
|
190
|
-
reject(e);
|
|
191
|
-
}
|
|
192
|
-
});
|
|
93
|
+
const wss = new WebSocket.Server({
|
|
94
|
+
server
|
|
95
|
+
});
|
|
96
|
+
wss.on('connection', ws => {
|
|
97
|
+
ws.on('error', err => {
|
|
98
|
+
// Ignore network errors like `ECONNRESET`, `EPIPE`, etc.
|
|
99
|
+
if (err.errno) return;
|
|
100
|
+
logger.info(err.message);
|
|
193
101
|
});
|
|
194
102
|
});
|
|
195
|
-
return
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
103
|
+
return {
|
|
104
|
+
ws: wss,
|
|
105
|
+
http: server,
|
|
106
|
+
updateChartData
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
function updateChartData(bundleStats) {
|
|
110
|
+
const newChartData = getChartData(analyzerOpts, bundleStats, bundleDir);
|
|
111
|
+
if (!newChartData) return;
|
|
112
|
+
chartData = newChartData;
|
|
113
|
+
wss.clients.forEach(client => {
|
|
114
|
+
if (client.readyState === WebSocket.OPEN) {
|
|
115
|
+
client.send(JSON.stringify({
|
|
116
|
+
event: 'chartDataUpdated',
|
|
117
|
+
data: newChartData
|
|
118
|
+
}));
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
}
|
|
200
122
|
}
|
|
201
123
|
|
|
202
|
-
function
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
124
|
+
async function generateReport(bundleStats, opts) {
|
|
125
|
+
const {
|
|
126
|
+
openBrowser = true,
|
|
127
|
+
reportFilename,
|
|
128
|
+
reportTitle,
|
|
129
|
+
bundleDir = null,
|
|
130
|
+
logger = new Logger(),
|
|
131
|
+
defaultSizes = 'parsed',
|
|
132
|
+
excludeAssets = null
|
|
133
|
+
} = opts || {};
|
|
134
|
+
const chartData = getChartData({
|
|
135
|
+
logger,
|
|
136
|
+
excludeAssets
|
|
137
|
+
}, bundleStats, bundleDir);
|
|
138
|
+
if (!chartData) return;
|
|
139
|
+
const reportHtml = renderViewer({
|
|
140
|
+
mode: 'static',
|
|
141
|
+
title: resolveTitle(reportTitle),
|
|
142
|
+
chartData,
|
|
143
|
+
defaultSizes,
|
|
144
|
+
enableWebSocket: false
|
|
218
145
|
});
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
146
|
+
const reportFilepath = path.resolve(bundleDir || process.cwd(), reportFilename);
|
|
147
|
+
fs.mkdirSync(path.dirname(reportFilepath), {
|
|
148
|
+
recursive: true
|
|
149
|
+
});
|
|
150
|
+
fs.writeFileSync(reportFilepath, reportHtml);
|
|
151
|
+
logger.info(`${bold('Webpack Bundle Analyzer')} saved report to ${bold(reportFilepath)}`);
|
|
224
152
|
|
|
225
|
-
if (
|
|
226
|
-
|
|
153
|
+
if (openBrowser) {
|
|
154
|
+
open(`file://${reportFilepath}`, logger);
|
|
227
155
|
}
|
|
228
|
-
|
|
229
|
-
return fs.readFileSync(assetPath, 'utf8');
|
|
230
156
|
}
|
|
231
|
-
/**
|
|
232
|
-
* Escapes `<` characters in JSON to safely use it in `<script>` tag.
|
|
233
|
-
*/
|
|
234
|
-
|
|
235
157
|
|
|
236
|
-
function
|
|
237
|
-
|
|
158
|
+
async function generateJSONReport(bundleStats, opts) {
|
|
159
|
+
const {
|
|
160
|
+
reportFilename,
|
|
161
|
+
bundleDir = null,
|
|
162
|
+
logger = new Logger(),
|
|
163
|
+
excludeAssets = null
|
|
164
|
+
} = opts || {};
|
|
165
|
+
const chartData = getChartData({
|
|
166
|
+
logger,
|
|
167
|
+
excludeAssets
|
|
168
|
+
}, bundleStats, bundleDir);
|
|
169
|
+
if (!chartData) return;
|
|
170
|
+
await fs.promises.mkdir(path.dirname(reportFilename), {
|
|
171
|
+
recursive: true
|
|
172
|
+
});
|
|
173
|
+
await fs.promises.writeFile(reportFilename, JSON.stringify(chartData));
|
|
174
|
+
logger.info(`${bold('Webpack Bundle Analyzer')} saved JSON report to ${bold(reportFilename)}`);
|
|
238
175
|
}
|
|
239
176
|
|
|
240
177
|
function getChartData(analyzerOpts, ...args) {
|