Skip to content

Commit

Permalink
Separate gzip and brotli data
Browse files Browse the repository at this point in the history
  • Loading branch information
dcsaszar committed Apr 15, 2021
1 parent 70d8cf1 commit 3f183c2
Show file tree
Hide file tree
Showing 14 changed files with 88 additions and 50 deletions.
12 changes: 8 additions & 4 deletions client/components/ModulesTreemap.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,15 @@ import {store} from '../store';
import ModulesList from './ModulesList';

function allSizeSwitchItems() {
return [
const items = [
{label: 'Stat', prop: 'statSize'},
{label: 'Parsed', prop: 'parsedSize'},
{label: window.compressedSizeLabel, prop: 'gzipSize'}
{label: 'Parsed', prop: 'parsedSize'}
];

if (window.compressionAlgorithm === 'gzip') items.push({label: 'Gzipped', prop: 'gzipSize'});
if (window.compressionAlgorithm === 'brotli') items.push({label: 'Brotli', prop: 'brotliSize'});

return items;
}

@observer
Expand Down Expand Up @@ -319,7 +323,7 @@ export default class ModulesTreemap extends Component {
<br/>
{this.renderModuleSize(module, 'stat')}
{!module.inaccurateSizes && this.renderModuleSize(module, 'parsed')}
{!module.inaccurateSizes && this.renderModuleSize(module, 'gzip')}
{!module.inaccurateSizes && this.renderModuleSize(module, window.compressionAlgorithm)}
{module.path &&
<div>Path: <strong>{module.path}</strong></div>
}
Expand Down
2 changes: 1 addition & 1 deletion client/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import localStorage from './localStorage';

export class Store {
cid = 0;
sizes = new Set(['statSize', 'parsedSize', 'gzipSize']);
sizes = new Set(['statSize', 'parsedSize', 'gzipSize', 'brotliSize']);

@observable.ref allChunks;
@observable.shallow selectedChunks;
Expand Down
1 change: 1 addition & 0 deletions src/BundleAnalyzerPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class BundleAnalyzerPlugin {
this.opts = {
analyzerMode: 'server',
analyzerHost: '127.0.0.1',
compressionAlgorithm: 'gzip',
reportFilename: null,
reportTitle: utils.defaultTitle,
defaultSizes: 'parsed',
Expand Down
15 changes: 4 additions & 11 deletions src/analyzer.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,11 @@ const Logger = require('./Logger');
const Folder = require('./tree/Folder').default;
const {parseBundle} = require('./parseUtils');
const {createAssetsFilter} = require('./utils');
const {gzipSize, brotliSize} = require('./sizeUtils');
const {compressedSize} = require('./sizeUtils');

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

const COMPRESSED_SIZE = {
gzip: gzipSize,
brotli: brotliSize
};

module.exports = {
getViewerData,
readStatsFromFile
Expand All @@ -31,9 +26,6 @@ function getViewerData(bundleStats, bundleDir, opts) {

const isAssetIncluded = createAssetsFilter(excludeAssets);

const compressedSize = COMPRESSED_SIZE[compressionAlgorithm];
if (!compressedSize) throw new Error(`Unsupported compression algorithm: ${compressionAlgorithm}.`);

// Sometimes all the information is located in `children` array (e.g. problem in #10)
if (_.isEmpty(bundleStats.assets) && !_.isEmpty(bundleStats.children)) {
const {children} = bundleStats;
Expand Down Expand Up @@ -111,7 +103,7 @@ function getViewerData(bundleStats, bundleDir, opts) {

if (assetSources) {
asset.parsedSize = Buffer.byteLength(assetSources.src);
asset.gzipSize = compressedSize(assetSources.src);
asset[`${compressionAlgorithm}Size`] = compressedSize(compressionAlgorithm, assetSources.src);
}

// Picking modules from current bundle script
Expand Down Expand Up @@ -152,7 +144,7 @@ function getViewerData(bundleStats, bundleDir, opts) {
}

asset.modules = assetModules;
asset.tree = createModulesTree(asset.modules, {compressedSize});
asset.tree = createModulesTree(asset.modules, {compressionAlgorithm});
return result;
}, {});

Expand All @@ -166,6 +158,7 @@ function getViewerData(bundleStats, bundleDir, opts) {
statSize: asset.tree.size || asset.size,
parsedSize: asset.parsedSize,
gzipSize: asset.gzipSize,
brotliSize: asset.brotliSize,
groups: _.invokeMap(asset.tree.children, 'toChartData')
}));
}
Expand Down
15 changes: 13 additions & 2 deletions src/sizeUtils.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
const zlib = require('zlib');

export function gzipSize(input) {
const COMPRESSED_SIZE = {
gzip: gzipSize,
brotli: brotliSize
};

export function compressedSize(compressionAlgorithm, input) {
const fn = COMPRESSED_SIZE[compressionAlgorithm];
if (!fn) throw new Error(`Unsupported compression algorithm: ${compressionAlgorithm}.`);
return fn(input);
}

function gzipSize(input) {
return zlib.gzipSync(input, {level: 9}).length;
}

export function brotliSize(input) {
function brotliSize(input) {
if (typeof zlib.brotliCompressSync !== 'function') {
throw new Error('Brotli compression requires Node.js v10.16.0 or higher.');
}
Expand Down
4 changes: 2 additions & 2 deletions src/template.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ function getScript(filename, mode) {
}
}

function renderViewer({title, enableWebSocket, chartData, defaultSizes, compressedSizeLabel, mode} = {}) {
function renderViewer({title, enableWebSocket, chartData, defaultSizes, compressionAlgorithm, mode} = {}) {
return html`<!DOCTYPE html>
<html>
<head>
Expand All @@ -59,7 +59,7 @@ function renderViewer({title, enableWebSocket, chartData, defaultSizes, compress
<script>
window.chartData = ${escapeJson(chartData)};
window.defaultSizes = ${escapeJson(defaultSizes)};
window.compressedSizeLabel = ${escapeJson(compressedSizeLabel)};
window.compressionAlgorithm = ${escapeJson(compressionAlgorithm)};
</script>
</body>
</html>`;
Expand Down
4 changes: 2 additions & 2 deletions src/tree/ConcatenatedModule.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import {getModulePathParts} from './utils';

export default class ConcatenatedModule extends Module {

constructor(name, data, parent) {
super(name, data, parent);
constructor(name, data, parent, opts) {
super(name, data, parent, opts);
this.name += ' (concatenated)';
this.children = Object.create(null);
this.fillContentModules();
Expand Down
5 changes: 5 additions & 0 deletions src/tree/ContentFolder.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ export default class ContentFolder extends BaseFolder {
return this.getSize('gzipSize');
}

get brotliSize() {
return this.getSize('brotliSize');
}

getSize(sizeType) {
const ownerModuleSize = this.ownerModule[sizeType];

Expand All @@ -28,6 +32,7 @@ export default class ContentFolder extends BaseFolder {
...super.toChartData(),
parsedSize: this.parsedSize,
gzipSize: this.gzipSize,
brotliSize: this.brotliSize,
inaccurateSizes: true
};
}
Expand Down
4 changes: 4 additions & 0 deletions src/tree/ContentModule.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ export default class ContentModule extends Module {
return this.getSize('gzipSize');
}

get brotliSize() {
return this.getSize('brotliSize');
}

getSize(sizeType) {
const ownerModuleSize = this.ownerModule[sizeType];

Expand Down
21 changes: 16 additions & 5 deletions src/tree/Folder.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Module from './Module';
import BaseFolder from './BaseFolder';
import ConcatenatedModule from './ConcatenatedModule';
import {getModulePathParts} from './utils';
import {compressedSize} from '../sizeUtils';

export default class Folder extends BaseFolder {

Expand All @@ -17,11 +18,20 @@ export default class Folder extends BaseFolder {
}

get gzipSize() {
if (!_.has(this, '_gzipSize')) {
this._gzipSize = this.src ? this.opts.compressedSize(this.src) : 0;
return this.opts.compressionAlgorithm === 'gzip' ? this.compressedSize('gzip') : undefined;
}

get brotliSize() {
return this.opts.compressionAlgorithm === 'brotli' ? this.compressedSize('brotli') : undefined;
}

compressedSize(compressionAlgorithm) {
const key = `_${compressionAlgorithm}Size`;
if (!_.has(this, key)) {
this[key] = this.src ? compressedSize(compressionAlgorithm, this.src) : 0;
}

return this._gzipSize;
return this[key];
}

addModule(moduleData) {
Expand Down Expand Up @@ -53,15 +63,16 @@ export default class Folder extends BaseFolder {
});

const ModuleConstructor = moduleData.modules ? ConcatenatedModule : Module;
const module = new ModuleConstructor(fileName, moduleData, this);
const module = new ModuleConstructor(fileName, moduleData, this, this.opts);
currentFolder.addChildModule(module);
}

toChartData() {
return {
...super.toChartData(),
parsedSize: this.parsedSize,
gzipSize: this.gzipSize
gzipSize: this.gzipSize,
brotliSize: this.brotliSize
};
}

Expand Down
24 changes: 18 additions & 6 deletions src/tree/Module.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import _ from 'lodash';
import {gzipSize} from '../sizeUtils';
import {compressedSize} from '../sizeUtils';

import Node from './Node';

export default class Module extends Node {

constructor(name, data, parent) {
constructor(name, data, parent, opts) {
super(name, parent);
this.data = data;
this.opts = opts;
}

get src() {
Expand All @@ -17,6 +18,7 @@ export default class Module extends Node {
set src(value) {
this.data.parsedSrc = value;
delete this._gzipSize;
delete this._brotliSize;
}

get size() {
Expand All @@ -32,11 +34,20 @@ export default class Module extends Node {
}

get gzipSize() {
if (!_.has(this, '_gzipSize')) {
this._gzipSize = this.src ? gzipSize(this.src) : undefined;
return this.opts.compressionAlgorithm === 'gzip' ? this.compressedSize('gzip') : undefined;
}

get brotliSize() {
return this.opts.compressionAlgorithm === 'brotli' ? this.compressedSize('brotli') : undefined;
}

compressedSize(compressionAlgorithm) {
const key = `_${compressionAlgorithm}Size`;
if (!_.has(this, key)) {
this[key] = this.src ? compressedSize(compressionAlgorithm, this.src) : undefined;
}

return this._gzipSize;
return this[key];
}

mergeData(data) {
Expand All @@ -56,7 +67,8 @@ export default class Module extends Node {
path: this.path,
statSize: this.size,
parsedSize: this.parsedSize,
gzipSize: this.gzipSize
gzipSize: this.gzipSize,
brotliSize: this.brotliSize
};
}

Expand Down
14 changes: 5 additions & 9 deletions src/viewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,6 @@ function resolveDefaultSizes(defaultSizes) {
return defaultSizes === 'compressed' ? 'gzip' : defaultSizes;
}

function resolveCompressedSizeLabel(compressionAlgorithm) {
return {gzip: 'Gzipped', brotli: 'Brotli'}[compressionAlgorithm];
}

module.exports = {
startServer,
generateReport,
Expand All @@ -48,7 +44,7 @@ async function startServer(bundleStats, opts) {
defaultSizes = 'parsed',
excludeAssets = null,
reportTitle,
compressionAlgorithm = 'gzip'
compressionAlgorithm
} = opts || {};

const analyzerOpts = {logger, excludeAssets, compressionAlgorithm};
Expand All @@ -69,7 +65,7 @@ async function startServer(bundleStats, opts) {
title: resolveTitle(reportTitle),
chartData,
defaultSizes: resolveDefaultSizes(defaultSizes),
compressedSizeLabel: resolveCompressedSizeLabel(compressionAlgorithm),
compressionAlgorithm,
enableWebSocket: true
});
res.writeHead(200, {'Content-Type': 'text/html'});
Expand Down Expand Up @@ -136,7 +132,7 @@ async function generateReport(bundleStats, opts) {
openBrowser = true,
reportFilename,
reportTitle,
compressionAlgorithm = 'gzip',
compressionAlgorithm,
bundleDir = null,
logger = new Logger(),
defaultSizes = 'parsed',
Expand All @@ -152,7 +148,7 @@ async function generateReport(bundleStats, opts) {
title: resolveTitle(reportTitle),
chartData,
defaultSizes: resolveDefaultSizes(defaultSizes),
compressedSizeLabel: resolveCompressedSizeLabel(compressionAlgorithm),
compressionAlgorithm,
enableWebSocket: false
});
const reportFilepath = path.resolve(bundleDir || process.cwd(), reportFilename);
Expand All @@ -169,7 +165,7 @@ async function generateReport(bundleStats, opts) {

async function generateJSONReport(bundleStats, opts) {
const {reportFilename, bundleDir = null, logger = new Logger(), excludeAssets = null,
compressionAlgorithm = 'gzip'} = opts || {};
compressionAlgorithm} = opts || {};

const chartData = getChartData({logger, excludeAssets, compressionAlgorithm}, bundleStats, bundleDir);

Expand Down
10 changes: 5 additions & 5 deletions test/analyzer.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,17 +220,17 @@ describe('Analyzer', function () {
describe('compression algorithm', function () {
it('should accept --compression-algorithm brotli', async function () {
generateReportFrom('with-modules-chunk.json', '--compression-algorithm brotli');
expect(await getCompressedSizeLabel()).to.equal('Brotli');
expect(await getCompressionAlgorithm()).to.equal('brotli');
});

it('should accept --compression-algorithm gzip', async function () {
generateReportFrom('with-modules-chunk.json', '--compression-algorithm gzip');
expect(await getCompressedSizeLabel()).to.equal('Gzipped');
expect(await getCompressionAlgorithm()).to.equal('gzip');
});

it('should default to gzip', async function () {
generateReportFrom('with-modules-chunk.json');
expect(await getCompressedSizeLabel()).to.equal('Gzipped');
expect(await getCompressionAlgorithm()).to.equal('gzip');
});
});
});
Expand Down Expand Up @@ -258,9 +258,9 @@ async function getChartData() {
return await nightmare.goto(`file://${__dirname}/output/report.html`).evaluate(() => window.chartData);
}

async function getCompressedSizeLabel() {
async function getCompressionAlgorithm() {
return await nightmare.goto(`file://${__dirname}/output/report.html`).evaluate(
() => window.compressedSizeLabel);
() => window.compressionAlgorithm);
}

function forEachChartItem(chartData, cb) {
Expand Down
Loading

0 comments on commit 3f183c2

Please sign in to comment.