@mui/internal-bundle-size-checker 1.0.6 → 1.0.9-canary.0
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.
- package/package.json +2 -1
- package/src/renderMarkdownReport.js +78 -22
- package/src/renderMarkdownReport.test.js +18 -24
- package/src/viteBuilder.js +7 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mui/internal-bundle-size-checker",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9-canary.0",
|
|
4
4
|
"description": "Bundle size checker for MUI packages.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
"@types/webpack-bundle-analyzer": "^4.7.0",
|
|
49
49
|
"@types/yargs": "^17.0.33"
|
|
50
50
|
},
|
|
51
|
+
"gitSha": "1c2b2282d97b7e09cf2d01ccc23046544f4e36ba",
|
|
51
52
|
"scripts": {
|
|
52
53
|
"typescript": "tsc -p tsconfig.json",
|
|
53
54
|
"test": "pnpm -w test --project @mui/internal-bundle-size-checker"
|
|
@@ -69,6 +69,51 @@ function generateEmphasizedChange({ id: bundle, parsed, gzip }) {
|
|
|
69
69
|
return `**${bundle}** **parsed:** ${changeParsed} **gzip:** ${changeGzip}`;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
/**
|
|
73
|
+
* @typedef {Object} ColumnDefinition
|
|
74
|
+
* @property {string} field - The property key to extract from data objects
|
|
75
|
+
* @property {string} [header] - Column header (defaults to field name)
|
|
76
|
+
* @property {'left'|'center'|'right'} [align='left'] - Column alignment
|
|
77
|
+
*/
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Formats data as a markdown table
|
|
81
|
+
* @param {ColumnDefinition[]} columns - Column definitions
|
|
82
|
+
* @param {Partial<Record<string, unknown>>[]} data - Array of data objects
|
|
83
|
+
* @returns {string} Formatted markdown table
|
|
84
|
+
*/
|
|
85
|
+
function formatMarkdownTable(columns, data) {
|
|
86
|
+
let table = '';
|
|
87
|
+
|
|
88
|
+
// Extract headers and alignments from column definitions
|
|
89
|
+
const headers = columns.map((col) => col.header || col.field);
|
|
90
|
+
const alignments = columns.map((col) => col.align || 'left');
|
|
91
|
+
|
|
92
|
+
// Header row
|
|
93
|
+
table += `| ${headers.join(' | ')} |\n`;
|
|
94
|
+
|
|
95
|
+
// Separator row with alignment
|
|
96
|
+
const separators = alignments.map((align) => {
|
|
97
|
+
switch (align) {
|
|
98
|
+
case 'center':
|
|
99
|
+
return ':----------:';
|
|
100
|
+
case 'right':
|
|
101
|
+
return '----------:';
|
|
102
|
+
default:
|
|
103
|
+
return '----------';
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
table += `|${separators.join('|')}|\n`;
|
|
107
|
+
|
|
108
|
+
// Data rows
|
|
109
|
+
data.forEach((row) => {
|
|
110
|
+
const cells = columns.map((col) => row[col.field] ?? '');
|
|
111
|
+
table += `| ${cells.join(' | ')} |\n`;
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
return table;
|
|
115
|
+
}
|
|
116
|
+
|
|
72
117
|
/**
|
|
73
118
|
* Generates a Markdown report for bundle size changes
|
|
74
119
|
* @param {ComparisonResult} comparison - Comparison result from calculateSizeDiff
|
|
@@ -92,9 +137,20 @@ export function renderMarkdownReportContent(
|
|
|
92
137
|
}
|
|
93
138
|
return trackedEntry;
|
|
94
139
|
});
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
140
|
+
|
|
141
|
+
markdownContent += formatMarkdownTable(
|
|
142
|
+
[
|
|
143
|
+
{ field: 'id', header: 'Bundle' },
|
|
144
|
+
{ field: 'parsed', header: 'Parsed Size', align: 'right' },
|
|
145
|
+
{ field: 'gzip', header: 'Gzip Size', align: 'right' },
|
|
146
|
+
],
|
|
147
|
+
trackedEntries.map(({ id, parsed, gzip }) => ({
|
|
148
|
+
id,
|
|
149
|
+
parsed: formatChange(parsed.absoluteDiff, parsed.relativeDiff),
|
|
150
|
+
gzip: formatChange(gzip.absoluteDiff, gzip.relativeDiff),
|
|
151
|
+
})),
|
|
152
|
+
);
|
|
153
|
+
markdownContent += '\n';
|
|
98
154
|
} else {
|
|
99
155
|
markdownContent += `**Total Size Change:** ${formatChange(
|
|
100
156
|
comparison.totals.totalParsed,
|
|
@@ -107,26 +163,26 @@ export function renderMarkdownReportContent(
|
|
|
107
163
|
markdownContent += `Files: ${comparison.fileCounts.total} total (${
|
|
108
164
|
comparison.fileCounts.added
|
|
109
165
|
} added, ${comparison.fileCounts.removed} removed, ${comparison.fileCounts.changed} changed)\n\n`;
|
|
110
|
-
}
|
|
111
166
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
167
|
+
// Show all entries in details section, not just changed ones
|
|
168
|
+
// Filter out tracked bundles to avoid duplication
|
|
169
|
+
const trackedIdSet = new Set(track);
|
|
170
|
+
const detailsEntries = comparison.entries.filter((entry) => !trackedIdSet.has(entry.id));
|
|
171
|
+
|
|
172
|
+
// Cap at maxDetailsLines bundles to avoid overly large reports
|
|
173
|
+
const cappedEntries = detailsEntries.slice(0, maxDetailsLines);
|
|
174
|
+
const hasMore = detailsEntries.length > maxDetailsLines;
|
|
175
|
+
|
|
176
|
+
if (cappedEntries.length > 0) {
|
|
177
|
+
const allChanges = cappedEntries.map(generateEmphasizedChange);
|
|
178
|
+
const bundleWord = cappedEntries.length === 1 ? 'bundle' : 'bundles';
|
|
179
|
+
const summaryText = hasMore
|
|
180
|
+
? `Show details for ${cappedEntries.length} more ${bundleWord} (${detailsEntries.length - maxDetailsLines} more not shown)`
|
|
181
|
+
: `Show details for ${cappedEntries.length} more ${bundleWord}`;
|
|
182
|
+
markdownContent += `<details>\n<summary>${summaryText}</summary>\n\n`;
|
|
183
|
+
markdownContent += `${allChanges.join('\n')}\n\n`;
|
|
184
|
+
markdownContent += `</details>`;
|
|
185
|
+
}
|
|
130
186
|
}
|
|
131
187
|
|
|
132
188
|
return markdownContent;
|
|
@@ -323,13 +323,12 @@ describe('renderMarkdownReport', () => {
|
|
|
323
323
|
});
|
|
324
324
|
|
|
325
325
|
expect(result).toMatchInlineSnapshot(`
|
|
326
|
-
"
|
|
327
|
-
|
|
328
|
-
|
|
326
|
+
"| Bundle | Parsed Size | Gzip Size |
|
|
327
|
+
|----------|----------:|----------:|
|
|
328
|
+
| @mui/material/Button/index.js | 🔺+400B<sup>(+2.67%)</sup> | 🔺+100B<sup>(+2.22%)</sup> |
|
|
329
|
+
| @mui/material/TextField/index.js | 🔺+200B<sup>(+0.91%)</sup> | 🔺+100B<sup>(+1.54%)</sup> |
|
|
329
330
|
|
|
330
|
-
**@mui/icons-material/Add.js** **parsed:** 🔺+100B<sup>(+10.00%)</sup> **gzip:** 🔺+50B<sup>(+16.67%)</sup>
|
|
331
331
|
|
|
332
|
-
</details>
|
|
333
332
|
|
|
334
333
|
[Details of bundle changes](https://frontend-public.mui.com/size-comparison/mui/material-ui/diff?prNumber=42&baseRef=master&baseCommit=abc123&headCommit=def456)"
|
|
335
334
|
`);
|
|
@@ -359,13 +358,12 @@ describe('renderMarkdownReport', () => {
|
|
|
359
358
|
});
|
|
360
359
|
|
|
361
360
|
expect(result).toMatchInlineSnapshot(`
|
|
362
|
-
"
|
|
363
|
-
|
|
364
|
-
|
|
361
|
+
"| Bundle | Parsed Size | Gzip Size |
|
|
362
|
+
|----------|----------:|----------:|
|
|
363
|
+
| @mui/material/Button/index.js | 🔺+500B<sup>(+3.33%)</sup> | 🔺+150B<sup>(+3.33%)</sup> |
|
|
364
|
+
| @mui/material/TextField/index.js | 🔺+300B<sup>(+1.36%)</sup> | 🔺+150B<sup>(+2.31%)</sup> |
|
|
365
365
|
|
|
366
|
-
**@mui/icons-material/Add.js** **parsed:** 🔺+1KB<sup>(+100.00%)</sup> **gzip:** 🔺+300B<sup>(+100.00%)</sup>
|
|
367
366
|
|
|
368
|
-
</details>
|
|
369
367
|
|
|
370
368
|
[Details of bundle changes](https://frontend-public.mui.com/size-comparison/mui/material-ui/diff?prNumber=42&baseRef=master&baseCommit=abc123&headCommit=def456)"
|
|
371
369
|
`);
|
|
@@ -395,13 +393,11 @@ describe('renderMarkdownReport', () => {
|
|
|
395
393
|
});
|
|
396
394
|
|
|
397
395
|
expect(result).toMatchInlineSnapshot(`
|
|
398
|
-
"
|
|
399
|
-
|
|
396
|
+
"| Bundle | Parsed Size | Gzip Size |
|
|
397
|
+
|----------|----------:|----------:|
|
|
398
|
+
| @mui/material/Button/index.js | 🔺+400B<sup>(+2.67%)</sup> | 🔺+100B<sup>(+2.22%)</sup> |
|
|
400
399
|
|
|
401
|
-
**@mui/icons-material/Add.js** **parsed:** 🔺+100B<sup>(+10.00%)</sup> **gzip:** 🔺+50B<sup>(+16.67%)</sup>
|
|
402
|
-
**@mui/icons-material/Delete.js** **parsed:** 🔺+100B<sup>(+8.33%)</sup> **gzip:** 🔺+50B<sup>(+14.29%)</sup>
|
|
403
400
|
|
|
404
|
-
</details>
|
|
405
401
|
|
|
406
402
|
[Details of bundle changes](https://frontend-public.mui.com/size-comparison/mui/material-ui/diff?prNumber=42&baseRef=master&baseCommit=abc123&headCommit=def456)"
|
|
407
403
|
`);
|
|
@@ -431,13 +427,12 @@ describe('renderMarkdownReport', () => {
|
|
|
431
427
|
});
|
|
432
428
|
|
|
433
429
|
expect(result).toMatchInlineSnapshot(`
|
|
434
|
-
"
|
|
435
|
-
|
|
436
|
-
<
|
|
430
|
+
"| Bundle | Parsed Size | Gzip Size |
|
|
431
|
+
|----------|----------:|----------:|
|
|
432
|
+
| @mui/material/Button/index.js | 0B<sup>(0.00%)</sup> | 0B<sup>(0.00%)</sup> |
|
|
433
|
+
| @mui/material/TextField/index.js | 0B<sup>(0.00%)</sup> | 0B<sup>(0.00%)</sup> |
|
|
437
434
|
|
|
438
|
-
**@mui/material/Icon/index.js** **parsed:** 🔺+100B<sup>(+1.25%)</sup> **gzip:** 🔺+50B<sup>(+2.00%)</sup>
|
|
439
435
|
|
|
440
|
-
</details>
|
|
441
436
|
|
|
442
437
|
[Details of bundle changes](https://frontend-public.mui.com/size-comparison/mui/material-ui/diff?prNumber=42&baseRef=master&baseCommit=abc123&headCommit=def456)"
|
|
443
438
|
`);
|
|
@@ -465,12 +460,11 @@ describe('renderMarkdownReport', () => {
|
|
|
465
460
|
});
|
|
466
461
|
|
|
467
462
|
expect(result).toMatchInlineSnapshot(`
|
|
468
|
-
"
|
|
469
|
-
|
|
463
|
+
"| Bundle | Parsed Size | Gzip Size |
|
|
464
|
+
|----------|----------:|----------:|
|
|
465
|
+
| @mui/material/Button/index.js | 🔺+400B<sup>(+2.67%)</sup> | 🔺+100B<sup>(+2.22%)</sup> |
|
|
470
466
|
|
|
471
|
-
**@mui/material/TextField/index.js** **parsed:** 0B<sup>(0.00%)</sup> **gzip:** 0B<sup>(0.00%)</sup>
|
|
472
467
|
|
|
473
|
-
</details>
|
|
474
468
|
|
|
475
469
|
[Details of bundle changes](https://frontend-public.mui.com/size-comparison/mui/material-ui/diff?prNumber=42&baseRef=master&baseCommit=abc123&headCommit=def456)"
|
|
476
470
|
`);
|
package/src/viteBuilder.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
2
|
import fs from 'fs/promises';
|
|
3
|
-
import
|
|
3
|
+
import * as zlib from 'zlib';
|
|
4
|
+
import { promisify } from 'util';
|
|
4
5
|
import { build, transformWithEsbuild } from 'vite';
|
|
5
6
|
import { visualizer } from 'rollup-plugin-visualizer';
|
|
6
7
|
|
|
8
|
+
const gzipAsync = promisify(zlib.gzip);
|
|
9
|
+
|
|
7
10
|
const rootDir = process.cwd();
|
|
8
11
|
|
|
9
12
|
/**
|
|
@@ -199,11 +202,12 @@ async function processBundleSizes(outDir, entryName) {
|
|
|
199
202
|
|
|
200
203
|
// Calculate sizes
|
|
201
204
|
const parsed = Buffer.byteLength(fileContent);
|
|
202
|
-
const
|
|
205
|
+
const gzipBuffer = await gzipAsync(fileContent, { level: zlib.constants.Z_BEST_COMPRESSION });
|
|
206
|
+
const gzipSize = Buffer.byteLength(gzipBuffer);
|
|
203
207
|
|
|
204
208
|
// Use chunk key as the name, or fallback to entry name for main chunk
|
|
205
209
|
const chunkName = chunkKey === 'virtual:entry.tsx' ? entryName : chunkKey;
|
|
206
|
-
return /** @type {const} */ ([chunkName, { parsed, gzip }]);
|
|
210
|
+
return /** @type {const} */ ([chunkName, { parsed, gzip: gzipSize }]);
|
|
207
211
|
});
|
|
208
212
|
|
|
209
213
|
const chunkEntries = await Promise.all(chunkPromises);
|