webpack-bundle-analyzer 2.8.1 → 2.9.1

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.
@@ -62,11 +62,7 @@ class BundleAnalyzerPlugin {
62
62
  }
63
63
 
64
64
  generateStatsFile(stats) {
65
- let statsFilepath = this.opts.statsFilename;
66
-
67
- if (!path.isAbsolute(statsFilepath)) {
68
- statsFilepath = path.resolve(this.compiler.outputPath, statsFilepath);
69
- }
65
+ const statsFilepath = path.resolve(this.compiler.outputPath, this.opts.statsFilename);
70
66
 
71
67
  mkdir.sync(path.dirname(statsFilepath));
72
68
 
@@ -98,7 +94,7 @@ class BundleAnalyzerPlugin {
98
94
  generateStaticReport(stats) {
99
95
  viewer.generateReport(stats, {
100
96
  openBrowser: this.opts.openAnalyzer,
101
- reportFilename: this.opts.reportFilename,
97
+ reportFilename: path.resolve(this.compiler.outputPath, this.opts.reportFilename),
102
98
  bundleDir: this.getBundleDirFromCompiler(),
103
99
  logger: this.logger,
104
100
  defaultSizes: this.opts.defaultSizes
package/src/analyzer.js CHANGED
@@ -9,6 +9,7 @@ const { Folder } = require('../lib/tree');
9
9
  const { parseBundle } = require('../lib/parseUtils');
10
10
 
11
11
  const FILENAME_QUERY_REGEXP = /\?.*$/;
12
+ const MULTI_MODULE_REGEXP = /^multi /;
12
13
 
13
14
  module.exports = {
14
15
  getViewerData,
@@ -35,7 +36,6 @@ function getViewerData(bundleStats, bundleDir, opts) {
35
36
  });
36
37
 
37
38
  // Trying to parse bundle assets and get real module sizes if `bundleDir` is provided
38
- let parsedModuleSizes = null;
39
39
  let bundlesSources = null;
40
40
  let parsedModules = null;
41
41
 
@@ -53,10 +53,7 @@ function getViewerData(bundleStats, bundleDir, opts) {
53
53
  bundleInfo = null;
54
54
  }
55
55
 
56
- if (bundleInfo) {
57
- bundlesSources[statAsset.name] = bundleInfo.src;
58
- _.assign(parsedModules, bundleInfo.modules);
59
- } else {
56
+ if (!bundleInfo) {
60
57
  logger.warn(
61
58
  `\nCouldn't parse bundle asset "${assetFile}".\n` +
62
59
  'Analyzer will use module sizes from stats file.\n'
@@ -65,15 +62,9 @@ function getViewerData(bundleStats, bundleDir, opts) {
65
62
  bundlesSources = null;
66
63
  break;
67
64
  }
68
- }
69
65
 
70
- if (parsedModules) {
71
- parsedModuleSizes = _.mapValues(parsedModules,
72
- moduleSrc => ({
73
- raw: moduleSrc.length,
74
- gzip: gzipSize.sync(moduleSrc)
75
- })
76
- );
66
+ bundlesSources[statAsset.name] = bundleInfo.src;
67
+ _.assign(parsedModules, bundleInfo.modules);
77
68
  }
78
69
  }
79
70
 
@@ -89,9 +80,8 @@ function getViewerData(bundleStats, bundleDir, opts) {
89
80
  asset.modules = _(bundleStats.modules)
90
81
  .filter(statModule => assetHasModule(statAsset, statModule))
91
82
  .each(statModule => {
92
- if (parsedModuleSizes) {
93
- statModule.parsedSize = parsedModuleSizes[statModule.id].raw;
94
- statModule.gzipSize = parsedModuleSizes[statModule.id].gzip;
83
+ if (parsedModules) {
84
+ statModule.parsedSrc = parsedModules[statModule.id];
95
85
  }
96
86
  });
97
87
 
@@ -128,7 +118,7 @@ function createModulesTree(modules) {
128
118
  const root = new Folder('.');
129
119
 
130
120
  _.each(modules, module => {
131
- const path = getModulePath(module.name);
121
+ const path = getModulePath(module);
132
122
 
133
123
  if (path) {
134
124
  root.addModuleByPath(path, module);
@@ -138,10 +128,14 @@ function createModulesTree(modules) {
138
128
  return root;
139
129
  }
140
130
 
141
- function getModulePath(path) {
131
+ function getModulePath(module) {
132
+ if (MULTI_MODULE_REGEXP.test(module.identifier)) {
133
+ return [module.identifier];
134
+ }
135
+
142
136
  const parsedPath = _
143
137
  // Removing loaders from module path: they're joined by `!` and the last part is a raw module path
144
- .last(path.split('!'))
138
+ .last(module.name.split('!'))
145
139
  // Splitting module path into parts
146
140
  .split('/')
147
141
  // Removing first `.`
package/src/parseUtils.js CHANGED
@@ -8,9 +8,14 @@ module.exports = {
8
8
  };
9
9
 
10
10
  function parseBundle(bundlePath) {
11
- const contentBuffer = fs.readFileSync(bundlePath);
12
- const contentStr = contentBuffer.toString('utf8');
13
- const ast = acorn.parse(contentStr, { sourceType: 'script' });
11
+ const content = fs.readFileSync(bundlePath, 'utf8');
12
+ const ast = acorn.parse(content, {
13
+ sourceType: 'script',
14
+ // I believe in a bright future of ECMAScript!
15
+ // Actually, it's set to `2050` to support the latest ECMAScript version that currently exists.
16
+ // Seems like `acorn` supports such weird option value.
17
+ ecmaVersion: 2050
18
+ });
14
19
 
15
20
  const walkState = {
16
21
  locations: null
@@ -78,9 +83,9 @@ function parseBundle(bundlePath) {
78
83
  }
79
84
 
80
85
  return {
81
- src: contentStr,
86
+ src: content,
82
87
  modules: _.mapValues(walkState.locations,
83
- loc => contentBuffer.toString('utf8', loc.start, loc.end)
88
+ loc => content.slice(loc.start, loc.end)
84
89
  )
85
90
  };
86
91
  }
@@ -139,7 +144,7 @@ function isArgumentArrayConcatContainingChunks(arg) {
139
144
  function isModuleWrapper(node) {
140
145
  return (
141
146
  // It's an anonymous function expression that wraps module
142
- (node.type === 'FunctionExpression' && !node.id) ||
147
+ ((node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression') && !node.id) ||
143
148
  // If `DedupePlugin` is used it can be an ID of duplicated module...
144
149
  isModuleId(node) ||
145
150
  // or an array of shape [<module_id>, ...args]
@@ -196,9 +201,5 @@ function getModulesLocationFromArrayConcat(arg) {
196
201
  }
197
202
 
198
203
  function getModuleLocation(node) {
199
- if (node.type === 'FunctionExpression') {
200
- node = node.body;
201
- }
202
-
203
204
  return _.pick(node, 'start', 'end');
204
205
  }
package/src/tree.js CHANGED
@@ -1,5 +1,6 @@
1
1
  const _ = require('lodash');
2
2
  const filesize = require('filesize');
3
+ const gzipSize = require('gzip-size');
3
4
 
4
5
  class Node {
5
6
 
@@ -35,24 +36,43 @@ class Module extends Node {
35
36
  this.data = data;
36
37
  }
37
38
 
39
+ get src() {
40
+ return this.data.parsedSrc;
41
+ }
42
+
43
+ set src(value) {
44
+ this.data.parsedSrc = value;
45
+ delete this._gzipSize;
46
+ }
47
+
38
48
  get size() {
39
49
  return this.data.size;
40
50
  }
41
51
 
52
+ set size(value) {
53
+ this.data.size = value;
54
+ }
55
+
42
56
  get parsedSize() {
43
- return this.data.parsedSize;
57
+ return this.src ? this.src.length : undefined;
44
58
  }
45
59
 
46
60
  get gzipSize() {
47
- return this.data.gzipSize;
61
+ if (!_.has(this, '_gzipSize')) {
62
+ this._gzipSize = this.src ? gzipSize.sync(this.src) : undefined;
63
+ }
64
+
65
+ return this._gzipSize;
48
66
  }
49
67
 
50
68
  mergeData(data) {
51
- _.each(['size', 'parsedSize', 'gzipSize'], prop => {
52
- if (data[prop]) {
53
- this.data[prop] = (this.data[prop] || 0) + data[prop];
54
- }
55
- });
69
+ if (data.size) {
70
+ this.size += data.size;
71
+ }
72
+
73
+ if (data.parsedSrc) {
74
+ this.src = (this.src || '') + data.parsedSrc;
75
+ }
56
76
  }
57
77
 
58
78
  toString(indent) {
@@ -80,37 +100,32 @@ class Folder extends Node {
80
100
  this.children = Object.create(null);
81
101
  }
82
102
 
103
+ get src() {
104
+ if (!_.has(this, '_src')) {
105
+ this._src = this.walk((node, src, stop) => {
106
+ if (node.src === undefined) return stop(undefined);
107
+ return (src += node.src);
108
+ }, '', false);
109
+ }
110
+
111
+ return this._src;
112
+ }
113
+
83
114
  get size() {
84
115
  if (!_.has(this, '_size')) {
85
- this._size = this.walk((node, size) => (size + node.size), 0);
116
+ this._size = this.walk((node, size) => (size + node.size), 0, false);
86
117
  }
87
118
 
88
119
  return this._size;
89
120
  }
90
121
 
91
122
  get parsedSize() {
92
- if (!_.has(this, '_parsedSize')) {
93
- this._parsedSize = this.walk((node, size, stop) => {
94
- if (node.parsedSize === undefined) {
95
- return stop(undefined);
96
- }
97
-
98
- return (size + node.parsedSize);
99
- }, 0);
100
- }
101
-
102
- return this._parsedSize;
123
+ return this.src ? this.src.length : undefined;
103
124
  }
104
125
 
105
126
  get gzipSize() {
106
127
  if (!_.has(this, '_gzipSize')) {
107
- this._gzipSize = this.walk((node, size, stop) => {
108
- if (node.gzipSize === undefined) {
109
- return stop(undefined);
110
- }
111
-
112
- return (size + node.gzipSize);
113
- }, 0);
128
+ this._gzipSize = this.src ? gzipSize.sync(this.src) : undefined;
114
129
  }
115
130
 
116
131
  return this._gzipSize;
@@ -125,7 +140,7 @@ class Folder extends Node {
125
140
 
126
141
  this.children[name] = folder;
127
142
  delete this._size;
128
- delete this._parsedSize;
143
+ delete this._src;
129
144
 
130
145
  return folder;
131
146
  }
@@ -147,7 +162,7 @@ class Folder extends Node {
147
162
  }
148
163
 
149
164
  delete this._size;
150
- delete this._parsedSize;
165
+ delete this._src;
151
166
 
152
167
  return true;
153
168
  }
@@ -177,11 +192,11 @@ class Folder extends Node {
177
192
  currentFolder.addModule(fileName, data);
178
193
  }
179
194
 
180
- walk(walker, state = {}) {
195
+ walk(walker, state = {}, deep = true) {
181
196
  let stopped = false;
182
197
 
183
198
  _.each(this.children, child => {
184
- if (child.walk) {
199
+ if (deep && child.walk) {
185
200
  state = child.walk(walker, state, stop);
186
201
  } else {
187
202
  state = walker(child, state, stop);
package/src/viewer.js CHANGED
@@ -59,7 +59,7 @@ async function startServer(bundleStats, opts) {
59
59
  server.listen(port, host, () => {
60
60
  resolve();
61
61
 
62
- const url = `http://${host}:${port}`;
62
+ const url = `http://${host}:${server.address().port}`;
63
63
 
64
64
  logger.info(
65
65
  `${bold('Webpack Bundle Analyzer')} is started at ${bold(url)}\n` +
@@ -122,11 +122,7 @@ function generateReport(bundleStats, opts) {
122
122
  (err, reportHtml) => {
123
123
  if (err) return logger.error(err);
124
124
 
125
- let reportFilepath = reportFilename;
126
-
127
- if (!path.isAbsolute(reportFilepath)) {
128
- reportFilepath = path.resolve(bundleDir || process.cwd(), reportFilepath);
129
- }
125
+ const reportFilepath = path.resolve(bundleDir || process.cwd(), reportFilename);
130
126
 
131
127
  mkdir.sync(path.dirname(reportFilepath));
132
128
  fs.writeFileSync(reportFilepath, reportHtml);