webpack-bundle-analyzer 3.5.2 → 3.8.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 +33 -0
- package/README.md +4 -3
- package/lib/BundleAnalyzerPlugin.js +23 -10
- package/lib/analyzer.js +1 -1
- package/lib/bin/analyzer.js +15 -5
- package/lib/parseUtils.js +32 -2
- package/lib/tree/ConcatenatedModule.js +1 -1
- package/lib/tree/ContentFolder.js +1 -1
- package/lib/tree/ContentModule.js +1 -1
- package/lib/tree/Folder.js +1 -1
- package/lib/utils.js +2 -2
- package/lib/viewer.js +26 -1
- package/package.json +9 -9
- package/public/viewer.js +4 -18
- package/public/viewer.js.map +1 -1
- package/src/BundleAnalyzerPlugin.js +13 -3
- package/src/bin/analyzer.js +17 -8
- package/src/parseUtils.js +37 -6
- package/src/utils.js +2 -2
- package/src/viewer.js +16 -4
|
@@ -7,12 +7,11 @@ const Logger = require('./Logger');
|
|
|
7
7
|
const viewer = require('./viewer');
|
|
8
8
|
|
|
9
9
|
class BundleAnalyzerPlugin {
|
|
10
|
-
|
|
11
10
|
constructor(opts = {}) {
|
|
12
11
|
this.opts = {
|
|
13
12
|
analyzerMode: 'server',
|
|
14
13
|
analyzerHost: '127.0.0.1',
|
|
15
|
-
reportFilename:
|
|
14
|
+
reportFilename: null,
|
|
16
15
|
defaultSizes: 'parsed',
|
|
17
16
|
openAnalyzer: true,
|
|
18
17
|
generateStatsFile: false,
|
|
@@ -51,6 +50,8 @@ class BundleAnalyzerPlugin {
|
|
|
51
50
|
actions.push(() => this.startAnalyzerServer(stats.toJson()));
|
|
52
51
|
} else if (this.opts.analyzerMode === 'static') {
|
|
53
52
|
actions.push(() => this.generateStaticReport(stats.toJson()));
|
|
53
|
+
} else if (this.opts.analyzerMode === 'json') {
|
|
54
|
+
actions.push(() => this.generateJSONReport(stats.toJson()));
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
if (actions.length) {
|
|
@@ -115,10 +116,19 @@ class BundleAnalyzerPlugin {
|
|
|
115
116
|
}
|
|
116
117
|
}
|
|
117
118
|
|
|
119
|
+
async generateJSONReport(stats) {
|
|
120
|
+
await viewer.generateJSONReport(stats, {
|
|
121
|
+
reportFilename: path.resolve(this.compiler.outputPath, this.opts.reportFilename || 'report.json'),
|
|
122
|
+
bundleDir: this.getBundleDirFromCompiler(),
|
|
123
|
+
logger: this.logger,
|
|
124
|
+
excludeAssets: this.opts.excludeAssets
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
118
128
|
async generateStaticReport(stats) {
|
|
119
129
|
await viewer.generateReport(stats, {
|
|
120
130
|
openBrowser: this.opts.openAnalyzer,
|
|
121
|
-
reportFilename: path.resolve(this.compiler.outputPath, this.opts.reportFilename),
|
|
131
|
+
reportFilename: path.resolve(this.compiler.outputPath, this.opts.reportFilename || 'report.html'),
|
|
122
132
|
bundleDir: this.getBundleDirFromCompiler(),
|
|
123
133
|
logger: this.logger,
|
|
124
134
|
defaultSizes: this.opts.defaultSizes,
|
package/src/bin/analyzer.js
CHANGED
|
@@ -26,9 +26,10 @@ const program = commander
|
|
|
26
26
|
)
|
|
27
27
|
.option(
|
|
28
28
|
'-m, --mode <mode>',
|
|
29
|
-
'Analyzer mode. Should be `server` or `
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
'Analyzer mode. Should be `server`,`static` or `json`.' +
|
|
30
|
+
br('In `server` mode analyzer will start HTTP server to show bundle report.') +
|
|
31
|
+
br('In `static` mode single HTML file with bundle report will be generated.') +
|
|
32
|
+
br('In `json` mode single JSON file with bundle report will be generated.'),
|
|
32
33
|
'server'
|
|
33
34
|
)
|
|
34
35
|
.option(
|
|
@@ -45,8 +46,7 @@ const program = commander
|
|
|
45
46
|
)
|
|
46
47
|
.option(
|
|
47
48
|
'-r, --report <file>',
|
|
48
|
-
'Path to bundle report file that will be generated in `static` mode.'
|
|
49
|
-
'report.html'
|
|
49
|
+
'Path to bundle report file that will be generated in `static` mode.'
|
|
50
50
|
)
|
|
51
51
|
.option(
|
|
52
52
|
'-s, --default-sizes <type>',
|
|
@@ -86,7 +86,9 @@ let {
|
|
|
86
86
|
const logger = new Logger(logLevel);
|
|
87
87
|
|
|
88
88
|
if (!bundleStatsFile) showHelp('Provide path to Webpack Stats file as first argument');
|
|
89
|
-
if (mode !== 'server' && mode !== 'static'
|
|
89
|
+
if (mode !== 'server' && mode !== 'static' && mode !== 'json') {
|
|
90
|
+
showHelp('Invalid mode. Should be either `server`, `static` or `json`.');
|
|
91
|
+
}
|
|
90
92
|
if (mode === 'server') {
|
|
91
93
|
if (!host) showHelp('Invalid host name');
|
|
92
94
|
|
|
@@ -118,15 +120,22 @@ if (mode === 'server') {
|
|
|
118
120
|
excludeAssets,
|
|
119
121
|
logger: new Logger(logLevel)
|
|
120
122
|
});
|
|
121
|
-
} else {
|
|
123
|
+
} else if (mode === 'static') {
|
|
122
124
|
viewer.generateReport(bundleStats, {
|
|
123
125
|
openBrowser,
|
|
124
|
-
reportFilename: resolve(reportFilename),
|
|
126
|
+
reportFilename: resolve(reportFilename || 'report.html'),
|
|
125
127
|
defaultSizes,
|
|
126
128
|
bundleDir,
|
|
127
129
|
excludeAssets,
|
|
128
130
|
logger: new Logger(logLevel)
|
|
129
131
|
});
|
|
132
|
+
} else if (mode === 'json') {
|
|
133
|
+
viewer.generateJSONReport(bundleStats, {
|
|
134
|
+
reportFilename: resolve(reportFilename || 'report.json'),
|
|
135
|
+
bundleDir,
|
|
136
|
+
excludeAssets,
|
|
137
|
+
logger: new Logger(logLevel)
|
|
138
|
+
});
|
|
130
139
|
}
|
|
131
140
|
|
|
132
141
|
function showHelp(error) {
|
package/src/parseUtils.js
CHANGED
|
@@ -25,6 +25,22 @@ function parseBundle(bundlePath) {
|
|
|
25
25
|
ast,
|
|
26
26
|
walkState,
|
|
27
27
|
{
|
|
28
|
+
AssignmentExpression(node, state) {
|
|
29
|
+
if (state.locations) return;
|
|
30
|
+
|
|
31
|
+
// Modules are stored in exports.modules:
|
|
32
|
+
// exports.modules = {};
|
|
33
|
+
const {left, right} = node;
|
|
34
|
+
|
|
35
|
+
if (
|
|
36
|
+
left &&
|
|
37
|
+
left.object && left.object.name === 'exports' &&
|
|
38
|
+
left.property && left.property.name === 'modules' &&
|
|
39
|
+
isModulesHash(right)
|
|
40
|
+
) {
|
|
41
|
+
state.locations = getModulesLocations(right);
|
|
42
|
+
}
|
|
43
|
+
},
|
|
28
44
|
CallExpression(node, state, c) {
|
|
29
45
|
if (state.locations) return;
|
|
30
46
|
|
|
@@ -63,6 +79,15 @@ function parseBundle(bundlePath) {
|
|
|
63
79
|
return;
|
|
64
80
|
}
|
|
65
81
|
|
|
82
|
+
// Webpack v4 WebWorkerChunkTemplatePlugin
|
|
83
|
+
// globalObject.chunkCallbackName([<chunks>],<modules>, ...);
|
|
84
|
+
// Both globalObject and chunkCallbackName can be changed through the config, so we can't check them.
|
|
85
|
+
if (isAsyncWebWorkerChunkExpression(node)) {
|
|
86
|
+
state.locations = getModulesLocations(args[1]);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
|
|
66
91
|
// Walking into arguments because some of plugins (e.g. `DedupePlugin`) or some Webpack
|
|
67
92
|
// features (e.g. `umd` library output) can wrap modules list into additional IIFE.
|
|
68
93
|
_.each(args, arg => c(arg, state));
|
|
@@ -182,12 +207,6 @@ function isAsyncChunkPushExpression(node) {
|
|
|
182
207
|
callee.type === 'MemberExpression' &&
|
|
183
208
|
callee.property.name === 'push' &&
|
|
184
209
|
callee.object.type === 'AssignmentExpression' &&
|
|
185
|
-
callee.object.left.object &&
|
|
186
|
-
(
|
|
187
|
-
callee.object.left.object.name === 'window' ||
|
|
188
|
-
// Webpack 4 uses `this` instead of `window`
|
|
189
|
-
callee.object.left.object.type === 'ThisExpression'
|
|
190
|
-
) &&
|
|
191
210
|
args.length === 1 &&
|
|
192
211
|
args[0].type === 'ArrayExpression' &&
|
|
193
212
|
mayBeAsyncChunkArguments(args[0].elements) &&
|
|
@@ -202,6 +221,18 @@ function mayBeAsyncChunkArguments(args) {
|
|
|
202
221
|
);
|
|
203
222
|
}
|
|
204
223
|
|
|
224
|
+
function isAsyncWebWorkerChunkExpression(node) {
|
|
225
|
+
const {callee, type, arguments: args} = node;
|
|
226
|
+
|
|
227
|
+
return (
|
|
228
|
+
type === 'CallExpression' &&
|
|
229
|
+
callee.type === 'MemberExpression' &&
|
|
230
|
+
args.length === 2 &&
|
|
231
|
+
isChunkIds(args[0]) &&
|
|
232
|
+
isModulesList(args[1])
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
|
|
205
236
|
function getModulesLocations(node) {
|
|
206
237
|
if (node.type === 'ObjectExpression') {
|
|
207
238
|
// Modules hash
|
package/src/utils.js
CHANGED
|
@@ -44,7 +44,7 @@ exports.getCurrentTime = function () {
|
|
|
44
44
|
const year = time.getFullYear();
|
|
45
45
|
const month = MONTHS[time.getMonth()];
|
|
46
46
|
const day = time.getDate();
|
|
47
|
-
const hour = time.getHours();
|
|
48
|
-
const minute = time.getMinutes();
|
|
47
|
+
const hour = `0${time.getHours()}`.slice(-2);
|
|
48
|
+
const minute = `0${time.getMinutes()}`.slice(-2);
|
|
49
49
|
return `${day} ${month} ${year} at ${hour}:${minute}`;
|
|
50
50
|
};
|
package/src/viewer.js
CHANGED
|
@@ -20,6 +20,7 @@ const assetsRoot = path.join(projectRoot, 'public');
|
|
|
20
20
|
module.exports = {
|
|
21
21
|
startServer,
|
|
22
22
|
generateReport,
|
|
23
|
+
generateJSONReport,
|
|
23
24
|
// deprecated
|
|
24
25
|
start: startServer
|
|
25
26
|
};
|
|
@@ -121,7 +122,7 @@ async function startServer(bundleStats, opts) {
|
|
|
121
122
|
async function generateReport(bundleStats, opts) {
|
|
122
123
|
const {
|
|
123
124
|
openBrowser = true,
|
|
124
|
-
reportFilename
|
|
125
|
+
reportFilename,
|
|
125
126
|
bundleDir = null,
|
|
126
127
|
logger = new Logger(),
|
|
127
128
|
defaultSizes = 'parsed',
|
|
@@ -158,9 +159,7 @@ async function generateReport(bundleStats, opts) {
|
|
|
158
159
|
mkdir.sync(path.dirname(reportFilepath));
|
|
159
160
|
fs.writeFileSync(reportFilepath, reportHtml);
|
|
160
161
|
|
|
161
|
-
logger.info(
|
|
162
|
-
`${bold('Webpack Bundle Analyzer')} saved report to ${bold(reportFilepath)}`
|
|
163
|
-
);
|
|
162
|
+
logger.info(`${bold('Webpack Bundle Analyzer')} saved report to ${bold(reportFilepath)}`);
|
|
164
163
|
|
|
165
164
|
if (openBrowser) {
|
|
166
165
|
opener(`file://${reportFilepath}`);
|
|
@@ -174,6 +173,19 @@ async function generateReport(bundleStats, opts) {
|
|
|
174
173
|
});
|
|
175
174
|
}
|
|
176
175
|
|
|
176
|
+
async function generateJSONReport(bundleStats, opts) {
|
|
177
|
+
const {reportFilename, bundleDir = null, logger = new Logger(), excludeAssets = null} = opts || {};
|
|
178
|
+
|
|
179
|
+
const chartData = getChartData({logger, excludeAssets}, bundleStats, bundleDir);
|
|
180
|
+
|
|
181
|
+
if (!chartData) return;
|
|
182
|
+
|
|
183
|
+
mkdir.sync(path.dirname(reportFilename));
|
|
184
|
+
fs.writeFileSync(reportFilename, JSON.stringify(chartData));
|
|
185
|
+
|
|
186
|
+
logger.info(`${bold('Webpack Bundle Analyzer')} saved JSON report to ${bold(reportFilename)}`);
|
|
187
|
+
}
|
|
188
|
+
|
|
177
189
|
function getAssetContent(filename) {
|
|
178
190
|
const assetPath = path.join(assetsRoot, filename);
|
|
179
191
|
|