@mui/internal-bundle-size-checker 1.0.9-canary.46 → 1.0.9-canary.48

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mui/internal-bundle-size-checker",
3
- "version": "1.0.9-canary.46",
3
+ "version": "1.0.9-canary.48",
4
4
  "description": "Bundle size checker for MUI packages.",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
@@ -19,8 +19,8 @@
19
19
  "./browser": "./src/browser.js"
20
20
  },
21
21
  "dependencies": {
22
- "@aws-sdk/client-s3": "^3.896.0",
23
- "@aws-sdk/credential-providers": "^3.896.0",
22
+ "@aws-sdk/client-s3": "^3.901.0",
23
+ "@aws-sdk/credential-providers": "^3.901.0",
24
24
  "@octokit/rest": "^22.0.0",
25
25
  "chalk": "^5.6.2",
26
26
  "env-ci": "^11.2.0",
@@ -29,7 +29,7 @@
29
29
  "micromatch": "^4.0.8",
30
30
  "piscina": "^5.1.3",
31
31
  "rollup-plugin-visualizer": "^6.0.3",
32
- "vite": "^7.1.7",
32
+ "vite": "^7.1.9",
33
33
  "yargs": "^18.0.0"
34
34
  },
35
35
  "devDependencies": {
@@ -37,7 +37,7 @@
37
37
  "@types/micromatch": "^4.0.9",
38
38
  "@types/yargs": "^17.0.33"
39
39
  },
40
- "gitSha": "8112fd2d7929c7e1b5f7475d1a4da16b62ba07cd",
40
+ "gitSha": "8ad4cd1aec96d0977bb91fd233e4fd7cd3ebd298",
41
41
  "scripts": {
42
42
  "typescript": "tsc -p tsconfig.json",
43
43
  "test": "pnpm -w test --project @mui/internal-bundle-size-checker"
package/src/builder.js CHANGED
@@ -4,6 +4,7 @@ import * as zlib from 'node:zlib';
4
4
  import { promisify } from 'node:util';
5
5
  import { build, transformWithEsbuild } from 'vite';
6
6
  import { visualizer } from 'rollup-plugin-visualizer';
7
+ import { escapeFilename } from './strings.js';
7
8
 
8
9
  const gzipAsync = promisify(zlib.gzip);
9
10
 
@@ -48,7 +49,7 @@ function createReplacePlugin(replacements) {
48
49
  * @param {ObjectEntry} entry - Entry point (string or object)
49
50
  * @param {CommandLineArgs} args
50
51
  * @param {Record<string, string>} [replacements] - String replacements to apply
51
- * @returns {Promise<import('vite').InlineConfig>}
52
+ * @returns {Promise<{ config:import('vite').InlineConfig, treemapPath: string }>}
52
53
  */
53
54
  async function createViteConfig(entry, args, replacements = {}) {
54
55
  const entryName = entry.id;
@@ -78,13 +79,15 @@ async function createViteConfig(entry, args, replacements = {}) {
78
79
  const externalsArray = entry.externals || ['react', 'react-dom'];
79
80
 
80
81
  // Ensure build directory exists
81
- const outDir = path.join(rootDir, 'build', entryName);
82
+ const outDir = path.join(rootDir, 'build', escapeFilename(entryName));
82
83
  await fs.mkdir(outDir, { recursive: true });
83
84
 
85
+ const treemapPath = path.join(outDir, 'treemap.html');
86
+
84
87
  /**
85
88
  * @type {import('vite').InlineConfig}
86
89
  */
87
- const configuration = {
90
+ const config = {
88
91
  configFile: false,
89
92
  root: rootDir,
90
93
 
@@ -112,7 +115,7 @@ async function createViteConfig(entry, args, replacements = {}) {
112
115
  ? [
113
116
  // File sizes are not accurate, use it only for relative comparison
114
117
  visualizer({
115
- filename: `${outDir}.html`,
118
+ filename: treemapPath,
116
119
  title: `Bundle Size Analysis: ${entryName}`,
117
120
  projectRoot: rootDir,
118
121
  open: false,
@@ -171,7 +174,7 @@ async function createViteConfig(entry, args, replacements = {}) {
171
174
  ],
172
175
  };
173
176
 
174
- return configuration;
177
+ return { config, treemapPath };
175
178
  }
176
179
 
177
180
  /**
@@ -275,19 +278,21 @@ async function processBundleSizes(output, entryName) {
275
278
  * @param {ObjectEntry} entry - The entry configuration
276
279
  * @param {CommandLineArgs} args - Command line arguments
277
280
  * @param {Record<string, string>} [replacements] - String replacements to apply
278
- * @returns {Promise<Map<string, SizeSnapshotEntry>>}
281
+ * @returns {Promise<{ sizes: Map<string, SizeSnapshotEntry>, treemapPath: string }>}
279
282
  */
280
283
  export async function getBundleSizes(entry, args, replacements) {
281
284
  // Create vite configuration
282
- const configuration = await createViteConfig(entry, args, replacements);
285
+ const { config, treemapPath } = await createViteConfig(entry, args, replacements);
283
286
 
284
287
  // Run vite build
285
- const { output } = /** @type {import('vite').Rollup.RollupOutput} */ (await build(configuration));
288
+ const { output } = /** @type {import('vite').Rollup.RollupOutput} */ (await build(config));
286
289
  const manifestChunk = output.find((chunk) => chunk.fileName === '.vite/manifest.json');
287
290
  if (!manifestChunk) {
288
291
  throw new Error(`Manifest file not found in output for entry: ${entry.id}`);
289
292
  }
290
293
 
291
294
  // Process the output to get bundle sizes
292
- return processBundleSizes(output, entry.id);
295
+ const sizes = await processBundleSizes(output, entry.id);
296
+
297
+ return { sizes, treemapPath };
293
298
  }
package/src/cli.js CHANGED
@@ -7,6 +7,8 @@ import yargs from 'yargs';
7
7
  import { Piscina } from 'piscina';
8
8
  import micromatch from 'micromatch';
9
9
  import envCi from 'env-ci';
10
+ import { pathToFileURL } from 'node:url';
11
+ import chalk from 'chalk';
10
12
  import { loadConfig } from './configLoader.js';
11
13
  import { uploadSnapshot } from './uploadSnapshot.js';
12
14
  import { renderMarkdownReport } from './renderMarkdownReport.js';
@@ -229,7 +231,9 @@ async function run(argv) {
229
231
  await fs.writeFile(snapshotDestPath, JSON.stringify(sortedBundleSizes, null, 2));
230
232
 
231
233
  // eslint-disable-next-line no-console
232
- console.log(`Bundle size snapshot written to ${snapshotDestPath}`);
234
+ console.log(
235
+ `Bundle size snapshot written to ${chalk.underline(pathToFileURL(snapshotDestPath))}`,
236
+ );
233
237
 
234
238
  // Upload the snapshot if upload configuration is provided and not null
235
239
  if (config && config.upload) {
package/src/strings.js ADDED
@@ -0,0 +1,38 @@
1
+ const illegalRe = /[/?<>\\:*|"]/g;
2
+ // eslint-disable-next-line no-control-regex
3
+ const controlRe = /[\x00-\x1f\x80-\x9f]/g;
4
+ const reservedRe = /^\.+$/;
5
+ const windowsReservedRe = /^(con|prn|aux|nul|com[0-9]|lpt[0-9])(\..*)?$/i;
6
+ const windowsTrailingRe = /[. ]+$/;
7
+
8
+ /**
9
+ * Inspired by https://github.com/parshap/node-sanitize-filename
10
+ *
11
+ * Replaces characters in strings that are illegal/unsafe for filenames.
12
+ * Unsafe characters are either removed or replaced by a substitute set
13
+ * in the optional `options` object.
14
+ *
15
+ * Illegal Characters on Various Operating Systems
16
+ * / ? < > \ : * | "
17
+ * https://kb.acronis.com/content/39790
18
+ *
19
+ * Unicode Control codes
20
+ * C0 0x00-0x1f & C1 (0x80-0x9f)
21
+ * http://en.wikipedia.org/wiki/C0_and_C1_control_codes
22
+ *
23
+ * Reserved filenames on Unix-based systems (".", "..")
24
+ * Reserved filenames in Windows ("CON", "PRN", "AUX", "NUL", "COM1",
25
+ * "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9",
26
+ * "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", and
27
+ * "LPT9") case-insesitively and with or without filename extensions.
28
+ * @param {string} input
29
+ */
30
+ export function escapeFilename(input, replacement = '_') {
31
+ const sanitized = input
32
+ .replace(illegalRe, replacement)
33
+ .replace(controlRe, replacement)
34
+ .replace(reservedRe, replacement)
35
+ .replace(windowsReservedRe, replacement)
36
+ .replace(windowsTrailingRe, replacement);
37
+ return sanitized;
38
+ }
package/src/worker.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import { pathToFileURL } from 'node:url';
2
- import path from 'node:path';
3
2
  import fs from 'node:fs/promises';
4
3
  import chalk from 'chalk';
5
4
  import * as module from 'node:module';
@@ -83,7 +82,7 @@ export default async function getSizes({ entry, args, index, total, replace }) {
83
82
  }
84
83
 
85
84
  try {
86
- const sizeMap = await getBundleSizes(entry, args, replace);
85
+ const { sizes: sizeMap, treemapPath } = await getBundleSizes(entry, args, replace);
87
86
 
88
87
  // Create a concise log message showing import details
89
88
  let entryDetails = '';
@@ -108,7 +107,7 @@ ${chalk.green('✓')} ${chalk.green.bold(`Completed ${index + 1}/${total}: [${en
108
107
  ${chalk.cyan('Import:')} ${entryDetails}
109
108
  ${chalk.cyan('Externals:')} ${entry.externals.join(', ')}
110
109
  ${chalk.cyan('Sizes:')} ${chalk.yellow(byteSizeFormatter.format(entrySize.parsed))} (${chalk.yellow(byteSizeFormatter.format(entrySize.gzip))} gzipped)
111
- ${args.analyze ? ` ${chalk.cyan('Analysis:')} ${chalk.underline(pathToFileURL(path.join(rootDir, 'build', `${entry.id}.html`)).href)}` : ''}
110
+ ${args.analyze ? ` ${chalk.cyan('Analysis:')} ${chalk.underline(pathToFileURL(treemapPath).href)}` : ''}
112
111
  `.trim(),
113
112
  );
114
113