Skip to content

Commit 80511a8

Browse files
committed
Add compressionAlgorithm option
1 parent 4dfbb5c commit 80511a8

File tree

8 files changed

+116
-16
lines changed

8 files changed

+116
-16
lines changed

client/components/ModulesTreemap.jsx

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@ import Search from './Search';
1818
import {store} from '../store';
1919
import ModulesList from './ModulesList';
2020

21-
const SIZE_SWITCH_ITEMS = [
22-
{label: 'Stat', prop: 'statSize'},
23-
{label: 'Parsed', prop: 'parsedSize'},
24-
{label: 'Gzipped', prop: 'gzipSize'}
25-
];
21+
function allSizeSwitchItems() {
22+
return [
23+
{label: 'Stat', prop: 'statSize'},
24+
{label: 'Parsed', prop: 'parsedSize'},
25+
{label: window.compressedSizeLabel, prop: 'gzipSize'}
26+
];
27+
}
2628

2729
@observer
2830
export default class ModulesTreemap extends Component {
@@ -138,7 +140,7 @@ export default class ModulesTreemap extends Component {
138140
renderModuleSize(module, sizeType) {
139141
const sizeProp = `${sizeType}Size`;
140142
const size = module[sizeProp];
141-
const sizeLabel = SIZE_SWITCH_ITEMS.find(item => item.prop === sizeProp).label;
143+
const sizeLabel = allSizeSwitchItems().find(item => item.prop === sizeProp).label;
142144
const isActive = (store.activeSize === sizeProp);
143145

144146
return (typeof size === 'number') ?
@@ -162,7 +164,8 @@ export default class ModulesTreemap extends Component {
162164
};
163165

164166
@computed get sizeSwitchItems() {
165-
return store.hasParsedSizes ? SIZE_SWITCH_ITEMS : SIZE_SWITCH_ITEMS.slice(0, 1);
167+
const items = allSizeSwitchItems();
168+
return store.hasParsedSizes ? items : items.slice(0, 1);
166169
}
167170

168171
@computed get activeSizeItem() {

src/BundleAnalyzerPlugin.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ class BundleAnalyzerPlugin {
104104
host: this.opts.analyzerHost,
105105
port: this.opts.analyzerPort,
106106
reportTitle: this.opts.reportTitle,
107+
compressionAlgorithm: this.opts.compressionAlgorithm,
107108
bundleDir: this.getBundleDirFromCompiler(),
108109
logger: this.logger,
109110
defaultSizes: this.opts.defaultSizes,
@@ -115,6 +116,7 @@ class BundleAnalyzerPlugin {
115116
async generateJSONReport(stats) {
116117
await viewer.generateJSONReport(stats, {
117118
reportFilename: path.resolve(this.compiler.outputPath, this.opts.reportFilename || 'report.json'),
119+
compressionAlgorithm: this.opts.compressionAlgorithm,
118120
bundleDir: this.getBundleDirFromCompiler(),
119121
logger: this.logger,
120122
excludeAssets: this.opts.excludeAssets
@@ -126,6 +128,7 @@ class BundleAnalyzerPlugin {
126128
openBrowser: this.opts.openAnalyzer,
127129
reportFilename: path.resolve(this.compiler.outputPath, this.opts.reportFilename || 'report.html'),
128130
reportTitle: this.opts.reportTitle,
131+
compressionAlgorithm: this.opts.compressionAlgorithm,
129132
bundleDir: this.getBundleDirFromCompiler(),
130133
logger: this.logger,
131134
defaultSizes: this.opts.defaultSizes,

src/analyzer.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,16 @@ const Logger = require('./Logger');
77
const Folder = require('./tree/Folder').default;
88
const {parseBundle} = require('./parseUtils');
99
const {createAssetsFilter} = require('./utils');
10-
const {gzipSize} = require('./sizeUtils');
10+
const {gzipSize, brotliSize} = require('./sizeUtils');
1111

1212
const FILENAME_QUERY_REGEXP = /\?.*$/u;
1313
const FILENAME_EXTENSIONS = /\.(js|mjs)$/iu;
1414

15+
const COMPRESSED_SIZE = {
16+
gzip: gzipSize,
17+
brotli: brotliSize
18+
};
19+
1520
module.exports = {
1621
getViewerData,
1722
readStatsFromFile
@@ -21,11 +26,14 @@ function getViewerData(bundleStats, bundleDir, opts) {
2126
const {
2227
logger = new Logger(),
2328
excludeAssets = null,
24-
compressedSize = gzipSize
29+
compressionAlgorithm
2530
} = opts || {};
2631

2732
const isAssetIncluded = createAssetsFilter(excludeAssets);
2833

34+
const compressedSize = COMPRESSED_SIZE[compressionAlgorithm];
35+
if (!compressedSize) throw new Error(`Unsupported compression algorithm: ${compressionAlgorithm}.`);
36+
2937
// Sometimes all the information is located in `children` array (e.g. problem in #10)
3038
if (_.isEmpty(bundleStats.assets) && !_.isEmpty(bundleStats.children)) {
3139
const {children} = bundleStats;

src/bin/analyzer.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ const utils = require('../utils');
1313
const SIZES = new Set(['stat', 'parsed', 'compressed']);
1414
const ACCEPTED_SIZES = new Set([...SIZES, 'gzip']);
1515

16+
const ALGORITHMS = new Set(['gzip', 'brotli']);
17+
1618
const program = commander
1719
.version(require('../../package.json').version)
1820
.usage(
@@ -59,6 +61,12 @@ const program = commander
5961
br(`Possible values: ${[...SIZES].join(', ')}`),
6062
'parsed'
6163
)
64+
.option(
65+
'--compression-algorithm <type>',
66+
'Compression algorithm that will be used to calculate the compressed module sizes.' +
67+
br(`Possible values: ${[...ALGORITHMS].join(', ')}`),
68+
'gzip'
69+
)
6270
.option(
6371
'-O, --no-open',
6472
"Don't open report in default browser automatically."
@@ -84,6 +92,7 @@ let {
8492
report: reportFilename,
8593
title: reportTitle,
8694
defaultSizes,
95+
compressionAlgorithm,
8796
logLevel,
8897
open: openBrowser,
8998
exclude: excludeAssets,
@@ -108,6 +117,9 @@ if (mode === 'server') {
108117
if (!ACCEPTED_SIZES.has(defaultSizes)) {
109118
showHelp(`Invalid default sizes option. Possible values are: ${[...SIZES].join(', ')}`);
110119
}
120+
if (!ALGORITHMS.has(compressionAlgorithm)) {
121+
showHelp(`Invalid compression algorithm option. Possible values are: ${[...ALGORITHMS].join(', ')}`);
122+
}
111123

112124
bundleStatsFile = resolve(bundleStatsFile);
113125

@@ -128,6 +140,7 @@ if (mode === 'server') {
128140
port,
129141
host,
130142
defaultSizes,
143+
compressionAlgorithm,
131144
reportTitle,
132145
bundleDir,
133146
excludeAssets,
@@ -139,13 +152,15 @@ if (mode === 'server') {
139152
reportFilename: resolve(reportFilename || 'report.html'),
140153
reportTitle,
141154
defaultSizes,
155+
compressionAlgorithm,
142156
bundleDir,
143157
excludeAssets,
144158
logger: new Logger(logLevel)
145159
});
146160
} else if (mode === 'json') {
147161
viewer.generateJSONReport(bundleStats, {
148162
reportFilename: resolve(reportFilename || 'report.json'),
163+
compressionAlgorithm,
149164
bundleDir,
150165
excludeAssets,
151166
logger: new Logger(logLevel)
@@ -159,7 +174,7 @@ function showHelp(error) {
159174
}
160175

161176
function br(str) {
162-
return `\n${' '.repeat(28)}${str}`;
177+
return `\n${' '.repeat(32)}${str}`;
163178
}
164179

165180
function array() {

src/template.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ function getScript(filename, mode) {
3939
}
4040
}
4141

42-
function renderViewer({title, enableWebSocket, chartData, defaultSizes, mode} = {}) {
42+
function renderViewer({title, enableWebSocket, chartData, defaultSizes, compressedSizeLabel, mode} = {}) {
4343
return html`<!DOCTYPE html>
4444
<html>
4545
<head>
@@ -59,6 +59,7 @@ function renderViewer({title, enableWebSocket, chartData, defaultSizes, mode} =
5959
<script>
6060
window.chartData = ${escapeJson(chartData)};
6161
window.defaultSizes = ${escapeJson(defaultSizes)};
62+
window.compressedSizeLabel = ${escapeJson(compressedSizeLabel)};
6263
</script>
6364
</body>
6465
</html>`;

src/viewer.js

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ function resolveDefaultSizes(defaultSizes) {
2626
return defaultSizes === 'compressed' ? 'gzip' : defaultSizes;
2727
}
2828

29+
function resolveCompressedSizeLabel(compressionAlgorithm) {
30+
return {gzip: 'Gzipped', brotli: 'Brotli'}[compressionAlgorithm];
31+
}
32+
2933
module.exports = {
3034
startServer,
3135
generateReport,
@@ -43,10 +47,11 @@ async function startServer(bundleStats, opts) {
4347
logger = new Logger(),
4448
defaultSizes = 'parsed',
4549
excludeAssets = null,
46-
reportTitle
50+
reportTitle,
51+
compressionAlgorithm = 'gzip'
4752
} = opts || {};
4853

49-
const analyzerOpts = {logger, excludeAssets};
54+
const analyzerOpts = {logger, excludeAssets, compressionAlgorithm};
5055

5156
let chartData = getChartData(analyzerOpts, bundleStats, bundleDir);
5257

@@ -64,6 +69,7 @@ async function startServer(bundleStats, opts) {
6469
title: resolveTitle(reportTitle),
6570
chartData,
6671
defaultSizes: resolveDefaultSizes(defaultSizes),
72+
compressedSizeLabel: resolveCompressedSizeLabel(compressionAlgorithm),
6773
enableWebSocket: true
6874
});
6975
res.writeHead(200, {'Content-Type': 'text/html'});
@@ -130,13 +136,14 @@ async function generateReport(bundleStats, opts) {
130136
openBrowser = true,
131137
reportFilename,
132138
reportTitle,
139+
compressionAlgorithm = 'gzip',
133140
bundleDir = null,
134141
logger = new Logger(),
135142
defaultSizes = 'parsed',
136143
excludeAssets = null
137144
} = opts || {};
138145

139-
const chartData = getChartData({logger, excludeAssets}, bundleStats, bundleDir);
146+
const chartData = getChartData({logger, excludeAssets, compressionAlgorithm}, bundleStats, bundleDir);
140147

141148
if (!chartData) return;
142149

@@ -145,6 +152,7 @@ async function generateReport(bundleStats, opts) {
145152
title: resolveTitle(reportTitle),
146153
chartData,
147154
defaultSizes: resolveDefaultSizes(defaultSizes),
155+
compressedSizeLabel: resolveCompressedSizeLabel(compressionAlgorithm),
148156
enableWebSocket: false
149157
});
150158
const reportFilepath = path.resolve(bundleDir || process.cwd(), reportFilename);
@@ -160,9 +168,10 @@ async function generateReport(bundleStats, opts) {
160168
}
161169

162170
async function generateJSONReport(bundleStats, opts) {
163-
const {reportFilename, bundleDir = null, logger = new Logger(), excludeAssets = null} = opts || {};
171+
const {reportFilename, bundleDir = null, logger = new Logger(), excludeAssets = null,
172+
compressionAlgorithm = 'gzip'} = opts || {};
164173

165-
const chartData = getChartData({logger, excludeAssets}, bundleStats, bundleDir);
174+
const chartData = getChartData({logger, excludeAssets, compressionAlgorithm}, bundleStats, bundleDir);
166175

167176
if (!chartData) return;
168177

test/analyzer.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,23 @@ describe('Analyzer', function () {
216216
expect(generatedReportTitle).to.match(/^webpack-bundle-analyzer \[.* at \d{2}:\d{2}\]/u);
217217
});
218218
});
219+
220+
describe('compression algorithm', function () {
221+
it('should accept --compression-algorithm brotli', async function () {
222+
generateReportFrom('with-modules-chunk.json', '--compression-algorithm brotli');
223+
expect(await getCompressedSizeLabel()).to.equal('Brotli');
224+
});
225+
226+
it('should accept --compression-algorithm gzip', async function () {
227+
generateReportFrom('with-modules-chunk.json', '--compression-algorithm gzip');
228+
expect(await getCompressedSizeLabel()).to.equal('Gzipped');
229+
});
230+
231+
it('should default to gzip', async function () {
232+
generateReportFrom('with-modules-chunk.json');
233+
expect(await getCompressedSizeLabel()).to.equal('Gzipped');
234+
});
235+
});
219236
});
220237
});
221238

@@ -241,6 +258,11 @@ async function getChartData() {
241258
return await nightmare.goto(`file://${__dirname}/output/report.html`).evaluate(() => window.chartData);
242259
}
243260

261+
async function getCompressedSizeLabel() {
262+
return await nightmare.goto(`file://${__dirname}/output/report.html`).evaluate(
263+
() => window.compressedSizeLabel);
264+
}
265+
244266
function forEachChartItem(chartData, cb) {
245267
for (const item of chartData) {
246268
cb(item);

test/plugin.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,45 @@ describe('Plugin', function () {
170170
expect(error).to.equal(reportTitleError);
171171
});
172172
});
173+
174+
describe('compressionAlgorithm', function () {
175+
it('should default to gzip', async function () {
176+
const config = makeWebpackConfig({
177+
analyzerOpts: {}
178+
});
179+
await webpackCompile(config, '4.44.2');
180+
await expectValidReport({
181+
parsedSize: 1311,
182+
gzipSize: 342
183+
});
184+
});
185+
186+
it('should support gzip', async function () {
187+
const config = makeWebpackConfig({
188+
analyzerOpts: {
189+
compressionAlgorithm: 'gzip'
190+
}
191+
});
192+
await webpackCompile(config, '4.44.2');
193+
await expectValidReport({
194+
parsedSize: 1311,
195+
gzipSize: 342
196+
});
197+
});
198+
199+
it('should support brotli', async function () {
200+
const config = makeWebpackConfig({
201+
analyzerOpts: {
202+
compressionAlgorithm: 'brotli'
203+
}
204+
});
205+
await webpackCompile(config, '4.44.2');
206+
await expectValidReport({
207+
parsedSize: 1311,
208+
gzipSize: 302
209+
});
210+
});
211+
});
173212
});
174213

175214
async function expectValidReport(opts) {

0 commit comments

Comments
 (0)