webpack-bundle-analyzer 3.3.0 → 3.4.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.
@@ -8,11 +8,10 @@ const viewer = require('./viewer');
8
8
 
9
9
  class BundleAnalyzerPlugin {
10
10
 
11
- constructor(opts) {
11
+ constructor(opts = {}) {
12
12
  this.opts = {
13
13
  analyzerMode: 'server',
14
14
  analyzerHost: '127.0.0.1',
15
- analyzerPort: 8888,
16
15
  reportFilename: 'report.html',
17
16
  defaultSizes: 'parsed',
18
17
  openAnalyzer: true,
@@ -23,7 +22,8 @@ class BundleAnalyzerPlugin {
23
22
  logLevel: 'info',
24
23
  // deprecated
25
24
  startAnalyzer: true,
26
- ...opts
25
+ ...opts,
26
+ analyzerPort: 'analyzerPort' in opts ? (opts.analyzerPort === 'auto' ? 0 : opts.analyzerPort) : 8888
27
27
  };
28
28
 
29
29
  this.server = null;
@@ -35,12 +35,11 @@ class BundleAnalyzerPlugin {
35
35
 
36
36
  const done = (stats, callback) => {
37
37
  callback = callback || (() => {});
38
- stats = stats.toJson(this.opts.statsOptions);
39
38
 
40
39
  const actions = [];
41
40
 
42
41
  if (this.opts.generateStatsFile) {
43
- actions.push(() => this.generateStatsFile(stats));
42
+ actions.push(() => this.generateStatsFile(stats.toJson(this.opts.statsOptions)));
44
43
  }
45
44
 
46
45
  // Handling deprecated `startAnalyzer` flag
@@ -49,9 +48,9 @@ class BundleAnalyzerPlugin {
49
48
  }
50
49
 
51
50
  if (this.opts.analyzerMode === 'server') {
52
- actions.push(() => this.startAnalyzerServer(stats));
51
+ actions.push(() => this.startAnalyzerServer(stats.toJson()));
53
52
  } else if (this.opts.analyzerMode === 'static') {
54
- actions.push(() => this.generateStaticReport(stats));
53
+ actions.push(() => this.generateStaticReport(stats.toJson()));
55
54
  }
56
55
 
57
56
  if (actions.length) {
@@ -128,7 +127,16 @@ class BundleAnalyzerPlugin {
128
127
  }
129
128
 
130
129
  getBundleDirFromCompiler() {
131
- return (this.compiler.outputFileSystem.constructor.name === 'MemoryFileSystem') ? null : this.compiler.outputPath;
130
+ switch (this.compiler.outputFileSystem.constructor.name) {
131
+ case 'MemoryFileSystem':
132
+ return null;
133
+ // Detect AsyncMFS used by Nuxt 2.5 that replaces webpack's MFS during development
134
+ // Related: #274
135
+ case 'AsyncMFS':
136
+ return null;
137
+ default:
138
+ return this.compiler.outputPath;
139
+ }
132
140
  }
133
141
 
134
142
  }
@@ -32,14 +32,15 @@ const program = commander
32
32
  'server'
33
33
  )
34
34
  .option(
35
- '-h, --host <host>',
35
+ // Had to make `host` parameter optional in order to let `-h` flag output help message
36
+ // Fixes https://github.com/webpack-contrib/webpack-bundle-analyzer/issues/239
37
+ '-h, --host [host]',
36
38
  'Host that will be used in `server` mode to start HTTP server.',
37
39
  '127.0.0.1'
38
40
  )
39
41
  .option(
40
42
  '-p, --port <n>',
41
43
  'Port that will be used in `server` mode to start HTTP server.',
42
- Number,
43
44
  8888
44
45
  )
45
46
  .option(
@@ -86,8 +87,12 @@ const logger = new Logger(logLevel);
86
87
 
87
88
  if (!bundleStatsFile) showHelp('Provide path to Webpack Stats file as first argument');
88
89
  if (mode !== 'server' && mode !== 'static') showHelp('Invalid mode. Should be either `server` or `static`.');
89
- if (mode === 'server' && !host) showHelp('Invalid host name');
90
- if (mode === 'server' && isNaN(port)) showHelp('Invalid port number');
90
+ if (mode === 'server') {
91
+ if (!host) showHelp('Invalid host name');
92
+
93
+ port = port === 'auto' ? 0 : Number(port);
94
+ if (isNaN(port)) showHelp('Invalid port. Should be a number or `auto`');
95
+ }
91
96
  if (!SIZES.has(defaultSizes)) showHelp(`Invalid default sizes option. Possible values are: ${[...SIZES].join(', ')}`);
92
97
 
93
98
  bundleStatsFile = resolve(bundleStatsFile);
@@ -125,7 +130,7 @@ if (mode === 'server') {
125
130
  }
126
131
 
127
132
  function showHelp(error) {
128
- if (error) console.log(`\n ${magenta(error)}`);
133
+ if (error) console.log(`\n ${magenta(error)}\n`);
129
134
  program.outputHelp();
130
135
  process.exit(1);
131
136
  }
package/src/viewer.js CHANGED
@@ -14,6 +14,7 @@ const Logger = require('./Logger');
14
14
  const analyzer = require('./analyzer');
15
15
 
16
16
  const projectRoot = path.resolve(__dirname, '..');
17
+ const assetsRoot = path.join(projectRoot, 'public');
17
18
 
18
19
  module.exports = {
19
20
  startServer,
@@ -51,9 +52,11 @@ async function startServer(bundleStats, opts) {
51
52
  app.use('/', (req, res) => {
52
53
  res.render('viewer', {
53
54
  mode: 'server',
54
- get chartData() { return JSON.stringify(chartData) },
55
- defaultSizes: JSON.stringify(defaultSizes),
56
- enableWebSocket: true
55
+ get chartData() { return chartData },
56
+ defaultSizes,
57
+ enableWebSocket: true,
58
+ // Helpers
59
+ escapeJson
57
60
  });
58
61
  });
59
62
 
@@ -130,10 +133,12 @@ async function generateReport(bundleStats, opts) {
130
133
  `${projectRoot}/views/viewer.ejs`,
131
134
  {
132
135
  mode: 'static',
133
- chartData: JSON.stringify(chartData),
136
+ chartData,
137
+ defaultSizes,
138
+ enableWebSocket: false,
139
+ // Helpers
134
140
  assetContent: getAssetContent,
135
- defaultSizes: JSON.stringify(defaultSizes),
136
- enableWebSocket: false
141
+ escapeJson
137
142
  },
138
143
  (err, reportHtml) => {
139
144
  try {
@@ -165,7 +170,20 @@ async function generateReport(bundleStats, opts) {
165
170
  }
166
171
 
167
172
  function getAssetContent(filename) {
168
- return fs.readFileSync(`${projectRoot}/public/${filename}`, 'utf8');
173
+ const assetPath = path.join(assetsRoot, filename);
174
+
175
+ if (!assetPath.startsWith(assetsRoot)) {
176
+ throw new Error(`"${filename}" is outside of the assets root`);
177
+ }
178
+
179
+ return fs.readFileSync(assetPath, 'utf8');
180
+ }
181
+
182
+ /**
183
+ * Escapes `<` characters in JSON to safely use it in `<script>` tag.
184
+ */
185
+ function escapeJson(json) {
186
+ return JSON.stringify(json).replace(/</gu, '\\u003c');
169
187
  }
170
188
 
171
189
  function getChartData(analyzerOpts, ...args) {
package/views/script.ejs CHANGED
@@ -4,5 +4,5 @@
4
4
  <%- assetContent(filename) %>
5
5
  </script>
6
6
  <% } else { %>
7
- <script src="/<%= filename %>"></script>
7
+ <script src="<%= filename %>"></script>
8
8
  <% } %>
package/views/viewer.ejs CHANGED
@@ -11,9 +11,9 @@
11
11
  <body>
12
12
  <div id="app"></div>
13
13
  <script>
14
- window.chartData = <%- chartData %>;
15
- window.defaultSizes = <%- defaultSizes %>;
16
- window.enableWebSocket = <%- enableWebSocket %>;
14
+ window.chartData = <%- escapeJson(chartData) %>;
15
+ window.defaultSizes = <%- escapeJson(defaultSizes) %>;
16
+ window.enableWebSocket = <%- escapeJson(enableWebSocket) %>;
17
17
  </script>
18
18
  </body>
19
19
  </html>