Skip to content

Commit

Permalink
feat: print file size grouped by environment (#2683)
Browse files Browse the repository at this point in the history
  • Loading branch information
9aoy authored Jun 24, 2024
1 parent b10c2b7 commit 45f5e4b
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 74 deletions.
9 changes: 8 additions & 1 deletion e2e/cases/performance/print-file-size/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ test.describe('should print file size correctly', async () => {
expect(logs.some((log) => log.includes('Gzipped size:'))).toBeTruthy();
});

test('should print size of multiple targets correctly', async () => {
test('should print size of multiple environments correctly', async () => {
await build({
cwd,
rsbuildConfig: {
Expand All @@ -59,6 +59,10 @@ test.describe('should print file size correctly', async () => {
});

// dist/index.html
expect(
logs.some((log) => log.includes('File') && log.includes('(web)')),
).toBeTruthy();

expect(
logs.some(
(log) =>
Expand All @@ -69,6 +73,9 @@ test.describe('should print file size correctly', async () => {
).toBeTruthy();

// dist/server/index.js
expect(
logs.some((log) => log.includes('File') && log.includes('(node)')),
).toBeTruthy();
expect(
logs.some(
(log) =>
Expand Down
165 changes: 92 additions & 73 deletions packages/core/src/plugins/fileSize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,7 @@ import fs from 'node:fs';
import path from 'node:path';
import { JS_REGEX } from '@rsbuild/shared';
import { color } from '@rsbuild/shared';
import type {
MultiStats,
PrintFileSizeOptions,
Stats,
StatsAsset,
} from '@rsbuild/shared';
import type { PrintFileSizeOptions, Stats, StatsAsset } from '@rsbuild/shared';
import { CSS_REGEX, HTML_REGEX } from '../constants';
import { logger } from '../logger';
import type { RsbuildPlugin } from '../types';
Expand All @@ -30,22 +25,26 @@ const getAssetColor = (size: number) => {
return color.green;
};

async function printHeader(
function getHeader(
longestFileLength: number,
longestLabelLength: number,
environment: string,
) {
const longestLengths = [longestFileLength, longestLabelLength];
const headerRow = ['File', 'Size', 'Gzipped'].reduce((prev, cur, index) => {
const length = longestLengths[index];
let curLabel = cur;
if (length) {
curLabel =
cur.length < length ? cur + ' '.repeat(length - cur.length) : cur;
}
return `${prev + curLabel} `;
}, ' ');
const headerRow = [`File (${environment})`, 'Size', 'Gzipped'].reduce(
(prev, cur, index) => {
const length = longestLengths[index];
let curLabel = cur;
if (length) {
curLabel =
cur.length < length ? cur + ' '.repeat(length - cur.length) : cur;
}
return `${prev + curLabel} `;
},
' ',
);

logger.log(color.bold(color.blue(headerRow)));
return color.bold(color.blue(headerRow));
}

const calcFileSize = (len: number) => {
Expand All @@ -68,11 +67,13 @@ const coloringAssetName = (assetName: string) => {

async function printFileSizes(
config: PrintFileSizeOptions,
stats: Stats | MultiStats,
stats: Stats,
rootPath: string,
environment: string,
) {
const logs: string[] = [];
if (config.detail === false && config.total === false) {
return;
return logs;
}

const { default: gzipSize } = await import('@rsbuild/shared/gzip-size');
Expand All @@ -97,55 +98,51 @@ async function printFileSizes(
};
};

const multiStats = 'stats' in stats ? stats.stats : [stats];
const assets = multiStats
.map((stats) => {
const distPath = stats.compilation.outputOptions.path;
const getAssets = () => {
const distPath = stats.compilation.outputOptions.path;

if (!distPath) {
return [];
}
if (!distPath) {
return [];
}

const origin = stats.toJson({
all: false,
assets: true,
// TODO: need supported in rspack
// @ts-expect-error
cachedAssets: true,
groupAssetsByInfo: false,
groupAssetsByPath: false,
groupAssetsByChunk: false,
groupAssetsByExtension: false,
groupAssetsByEmitStatus: false,
});
const origin = stats.toJson({
all: false,
assets: true,
// TODO: need supported in rspack
// @ts-expect-error
cachedAssets: true,
groupAssetsByInfo: false,
groupAssetsByPath: false,
groupAssetsByChunk: false,
groupAssetsByExtension: false,
groupAssetsByEmitStatus: false,
});

const filteredAssets = origin.assets!.filter((asset) =>
filterAsset(asset.name),
);
const filteredAssets = origin.assets!.filter((asset) =>
filterAsset(asset.name),
);

const distFolder = path.relative(rootPath, distPath);
const distFolder = path.relative(rootPath, distPath);

return filteredAssets.map((asset) =>
formatAsset(asset, distPath, distFolder),
);
})
.reduce((single, all) => all.concat(single), []);
return filteredAssets.map((asset) =>
formatAsset(asset, distPath, distFolder),
);
};
const assets = getAssets();

if (assets.length === 0) {
return;
return logs;
}

assets.sort((a, b) => a.size - b.size);

logger.info('Production file sizes:\n');

const longestLabelLength = Math.max(...assets.map((a) => a.sizeLabel.length));
const longestFileLength = Math.max(
...assets.map((a) => (a.folder + path.sep + a.name).length),
);

if (config.detail !== false) {
printHeader(longestFileLength, longestLabelLength);
logs.push(getHeader(longestFileLength, longestLabelLength, environment));
}

let totalSize = 0;
Expand Down Expand Up @@ -174,7 +171,7 @@ async function printFileSizes(
fileNameLabel += rightPadding;
}

logger.log(` ${fileNameLabel} ${sizeLabel} ${gzipSizeLabel}`);
logs.push(` ${fileNameLabel} ${sizeLabel} ${gzipSizeLabel}`);
}
}

Expand All @@ -185,39 +182,61 @@ async function printFileSizes(
const gzippedSizeLabel = `${color.bold(
color.blue('Gzipped size:'),
)} ${calcFileSize(totalGzipSize)}`;
logger.log(`\n ${totalSizeLabel}\n ${gzippedSizeLabel}\n`);
logs.push(`\n ${totalSizeLabel}\n ${gzippedSizeLabel}\n`);
}

return logs;
}

export const pluginFileSize = (): RsbuildPlugin => ({
name: 'rsbuild:file-size',

setup(api) {
api.onAfterBuild(async ({ stats }) => {
const { printFileSize } = api.getNormalizedConfig().performance;

if (printFileSize === false) {
if (!stats) {
return;
}

const printFileSizeConfig =
typeof printFileSize === 'boolean'
? {
total: true,
detail: true,
const logs = await Promise.all(
Object.keys(api.context.environments).map(
async (environment, index) => {
const { printFileSize } = api.getNormalizedConfig({
environment,
}).performance;

const multiStats = 'stats' in stats ? stats.stats : [stats];

const printFileSizeConfig =
typeof printFileSize === 'boolean'
? {
total: true,
detail: true,
}
: printFileSize;

if (printFileSize) {
return printFileSizes(
printFileSizeConfig,
multiStats[index],
api.context.rootPath,
environment,
);
}
: printFileSize;

if (stats) {
try {
await printFileSizes(
printFileSizeConfig,
stats,
api.context.rootPath,
);
} catch (err) {
logger.warn('Failed to print file size.');
logger.warn(err as Error);
return [];
},
),
).catch((err) => {
logger.warn('Failed to print file size.');
logger.warn(err as Error);
return [];
});

if (logs.filter((log) => log.length).length) {
logger.info('Production file sizes:\n');
for (const statsLog of logs) {
for (const log of statsLog) {
logger.log(log);
}
}
}
});
Expand Down

0 comments on commit 45f5e4b

Please sign in to comment.