|
3 | 3 | * |
4 | 4 | * This file determines which packages and components will have their bundle sizes measured. |
5 | 5 | */ |
6 | | -import fs from 'fs'; |
7 | | -import path from 'path'; |
8 | | -import { globby } from 'globby'; |
9 | 6 | import { defineConfig } from '@mui/internal-bundle-size-checker'; |
10 | 7 | import generateReleaseInfo from '../../scripts/generateReleaseInfo.mjs'; |
11 | 8 |
|
12 | | -const rootDir = path.resolve(import.meta.dirname, '../..'); |
| 9 | +// `expand` measures one entrypoint per sub-path export declared in a package's |
| 10 | +// (built) `package.json`, minus the `exclude` micromatch globs (matched against |
| 11 | +// the export subpath). The excludes below express *what is not a renderable |
| 12 | +// component*, so newly added components are tracked automatically. |
13 | 13 |
|
14 | | -async function findComponents(packageFolder, packageName) { |
15 | | - const pkgBuildFolder = path.join(rootDir, `packages/${packageFolder}/build`); |
16 | | - const pkgFiles = await globby(path.join(pkgBuildFolder, '([A-Z])*/index.js')); |
17 | | - const pkgComponents = pkgFiles.map((componentPath) => { |
18 | | - const componentName = path.basename(path.dirname(componentPath)); |
19 | | - return `${packageName}/${componentName}`; |
20 | | - }); |
21 | | - return pkgComponents; |
22 | | -} |
| 14 | +// Renderable components are PascalCase; every lowercase-first sub-path export |
| 15 | +// (hooks, models, locales, internals, utils, internals/demo, moduleAugmentation/*, …) |
| 16 | +// is a non-component. A single rule covers them at any depth. |
| 17 | +const componentPackage = { exclude: ['[a-z]*', '[a-z]*/**'] }; |
23 | 18 |
|
24 | | -// Sub-path exports that aren't renderable components and therefore shouldn't be |
25 | | -// tracked individually for bundle size (types, locales, augmentations, internals). |
26 | | -// Add to this denylist when introducing non-component sub-path exports (e.g. `utils`, `colors`). |
27 | | -const NON_COMPONENT_EXPORTS = new Set(['models', 'locales', 'theme-augmentation', 'internals']); |
| 19 | +// Date-pickers additionally ship deprecated v2 adapters we don't track. |
| 20 | +const pickersPackage = { |
| 21 | + exclude: [...componentPackage.exclude, 'AdapterDateFnsJalaliV2', 'AdapterDateFnsV2'], |
| 22 | +}; |
28 | 23 |
|
29 | | -/** |
30 | | - * Lists the component entrypoints of a package from its `exports` field. |
31 | | - * |
32 | | - * Unlike `findComponents`, which scans the build output for PascalCase component |
33 | | - * folders, this reads the explicit kebab-case sub-path exports used by the |
34 | | - * scheduler packages, so newly added views are tracked automatically without |
35 | | - * hardcoding them here. |
36 | | - */ |
37 | | -function findComponentsFromExports(packageFolder, packageName) { |
38 | | - const pkgJsonPath = path.join(rootDir, `packages/${packageFolder}/package.json`); |
39 | | - const { exports: pkgExports } = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf8')); |
40 | | - return Object.keys(pkgExports) |
41 | | - .filter((key) => key.startsWith('./')) |
42 | | - .map((key) => key.slice(2)) |
43 | | - .filter((name) => !NON_COMPONENT_EXPORTS.has(name) && !name.startsWith('use-')) |
44 | | - .map((name) => `${packageName}/${name}`); |
45 | | -} |
46 | | - |
47 | | -/** |
48 | | - * Generates the entrypoints configuration by scanning the project structure. |
49 | | - */ |
50 | | -export default defineConfig(async () => { |
51 | | - const [ |
52 | | - chartsComponents, |
53 | | - chartsProComponents, |
54 | | - chartsPremiumComponents, |
55 | | - datePickersComponents, |
56 | | - datePickersProComponents, |
57 | | - treeViewComponents, |
58 | | - treeViewProComponents, |
59 | | - ] = await Promise.all([ |
60 | | - findComponents('x-charts', '@mui/x-charts'), |
61 | | - findComponents('x-charts-pro', '@mui/x-charts-pro'), |
62 | | - findComponents('x-charts-premium', '@mui/x-charts-premium'), |
63 | | - findComponents('x-date-pickers', '@mui/x-date-pickers'), |
64 | | - findComponents('x-date-pickers-pro', '@mui/x-date-pickers-pro'), |
65 | | - findComponents('x-tree-view', '@mui/x-tree-view'), |
66 | | - findComponents('x-tree-view-pro', '@mui/x-tree-view-pro'), |
67 | | - ]); |
| 24 | +// Scheduler views are kebab-case (lowercase), so the case rule can't distinguish |
| 25 | +// them from non-components; deny the known non-view sub-paths instead. |
| 26 | +const schedulerPackage = { |
| 27 | + exclude: ['models', 'locales', 'theme-augmentation', 'internals', 'use-*'], |
| 28 | +}; |
68 | 29 |
|
69 | | - // Return the complete entrypoints configuration |
70 | | - return { |
71 | | - entrypoints: [ |
72 | | - '@mui/x-data-grid', |
73 | | - '@mui/x-data-grid/DataGrid', |
74 | | - '@mui/x-data-grid-pro', |
75 | | - '@mui/x-data-grid-pro/DataGridPro', |
76 | | - '@mui/x-data-grid-premium', |
77 | | - '@mui/x-data-grid-premium/DataGridPremium', |
78 | | - '@mui/x-charts', |
79 | | - ...chartsComponents, |
80 | | - '@mui/x-charts-pro', |
81 | | - ...chartsProComponents, |
82 | | - '@mui/x-charts-premium', |
83 | | - ...chartsPremiumComponents, |
84 | | - '@mui/x-date-pickers', |
85 | | - ...datePickersComponents.filter( |
86 | | - (component) => |
87 | | - !component.includes('AdapterDateFnsJalaliV2') && !component.includes('AdapterDateFnsV2'), |
88 | | - ), |
89 | | - '@mui/x-date-pickers-pro', |
90 | | - ...datePickersProComponents.filter( |
91 | | - (component) => |
92 | | - !component.includes('AdapterDateFnsJalaliV2') && !component.includes('AdapterDateFnsV2'), |
93 | | - ), |
94 | | - '@mui/x-tree-view', |
95 | | - ...treeViewComponents, |
96 | | - '@mui/x-tree-view-pro', |
97 | | - ...treeViewProComponents, |
98 | | - '@mui/x-scheduler', |
99 | | - ...findComponentsFromExports('x-scheduler', '@mui/x-scheduler'), |
100 | | - '@mui/x-scheduler-premium', |
101 | | - ...findComponentsFromExports('x-scheduler-premium', '@mui/x-scheduler-premium'), |
102 | | - '@mui/x-license', |
103 | | - '@mui/x-license/internals', |
104 | | - ], |
105 | | - upload: !!process.env.CI, |
106 | | - replace: { |
107 | | - // Stabilize release info string |
108 | | - [JSON.stringify(generateReleaseInfo())]: JSON.stringify('__RELEASE_INFO__'), |
109 | | - }, |
110 | | - comment: true, |
111 | | - }; |
| 30 | +export default defineConfig({ |
| 31 | + entrypoints: [ |
| 32 | + { id: '@mui/x-data-grid', expand: componentPackage }, |
| 33 | + { id: '@mui/x-data-grid-pro', expand: componentPackage }, |
| 34 | + { id: '@mui/x-data-grid-premium', expand: componentPackage }, |
| 35 | + { id: '@mui/x-charts', expand: componentPackage }, |
| 36 | + { id: '@mui/x-charts-pro', expand: componentPackage }, |
| 37 | + { id: '@mui/x-charts-premium', expand: componentPackage }, |
| 38 | + { id: '@mui/x-date-pickers', expand: pickersPackage }, |
| 39 | + { id: '@mui/x-date-pickers-pro', expand: pickersPackage }, |
| 40 | + { id: '@mui/x-tree-view', expand: componentPackage }, |
| 41 | + { id: '@mui/x-tree-view-pro', expand: componentPackage }, |
| 42 | + { id: '@mui/x-scheduler', expand: schedulerPackage }, |
| 43 | + { id: '@mui/x-scheduler-premium', expand: schedulerPackage }, |
| 44 | + { id: '@mui/x-chat', expand: componentPackage }, |
| 45 | + { id: '@mui/x-license', expand: componentPackage }, |
| 46 | + ], |
| 47 | + upload: !!process.env.CI, |
| 48 | + replace: { |
| 49 | + // Stabilize release info string |
| 50 | + [JSON.stringify(generateReleaseInfo())]: JSON.stringify('__RELEASE_INFO__'), |
| 51 | + }, |
| 52 | + comment: true, |
112 | 53 | }); |
0 commit comments