Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[code-infra] Build size snapshots from installed packages #43452

Merged
merged 11 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ packages:
- 'docs'
- 'test'
- 'apps/*'
- 'scripts/sizeSnapshot'
15 changes: 15 additions & 0 deletions scripts/sizeSnapshot/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "size-snapshot",
"version": "1.0.0",
"description": "Size snapshot of MUI packages",
"dependencies": {
"@mui/lab": "workspace:^",
"@mui/base": "workspace:^",
"@mui/joy": "workspace:^",
"@mui/material": "workspace:^",
"@mui/styles": "workspace:^",
"@mui/private-theming": "workspace:^",
"@mui/utils": "workspace:^",
"@mui/system": "workspace:^"
}
}
61 changes: 38 additions & 23 deletions scripts/sizeSnapshot/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ async function getWebpackEntries() {

return {
id: entryName,
path: path.relative(workspaceRoot, path.dirname(componentPath)),
import: `@mui/material/${componentName}`,
};
},
);

const corePackagePath = path.join(workspaceRoot, 'packages/mui-base/build');
const coreComponents = (await glob(path.join(corePackagePath, '([A-Z])*/index.js'))).map(
const baseComponents = (await glob(path.join(corePackagePath, '([A-Z])*/index.js'))).map(
(componentPath) => {
const componentName = path.basename(path.dirname(componentPath));
let entryName = componentName;
Expand All @@ -38,7 +38,7 @@ async function getWebpackEntries() {

return {
id: entryName,
path: path.relative(workspaceRoot, path.dirname(componentPath)),
import: `@mui/base/${componentName}`,
};
},
);
Expand All @@ -50,7 +50,7 @@ async function getWebpackEntries() {

return {
id: componentName,
path: path.relative(workspaceRoot, path.dirname(componentPath)),
import: `@mui/lab/${componentName}`,
};
},
);
Expand All @@ -62,7 +62,7 @@ async function getWebpackEntries() {

return {
id: `@mui/joy/${componentName}`,
path: path.relative(workspaceRoot, path.dirname(componentPath)),
import: `@mui/joy/${componentName}`,
};
},
);
Expand All @@ -72,62 +72,63 @@ async function getWebpackEntries() {
// WARNING: Changing the name will break tracking of bundle size over time
// If the name of the package changes, rename its display name in https://github.com/eps1lon/mui-contributor-dashboard/blob/main/src/pages/SizeComparison.tsx
id: '@material-ui/core',
path: path.join(path.relative(workspaceRoot, materialPackagePath), 'index.js'),
import: '@mui/material',
},
...materialComponents,
{
id: '@material-ui/lab',
path: path.join(path.relative(workspaceRoot, labPackagePath), 'index.js'),
import: '@mui/lab',
},
...labComponents,
{
id: '@material-ui/styles',
path: 'packages/mui-styles/build/index.js',
import: '@mui/styles',
},
{
id: '@material-ui/private-theming',
path: 'packages/mui-private-theming/build/index.js',
import: '@mui/private-theming',
},
{
id: '@material-ui/system',
path: 'packages/mui-system/build/index.js',
import: '@mui/system',
},
{
id: 'createBox',
path: 'packages/mui-system/build/createBox/index.js',
import: '@mui/system/createBox',
},
{
id: 'createStyled',
path: 'packages/mui-system/build/createStyled/index.js',
import: '@mui/system/createStyled',
},
{
id: '@material-ui/core/styles/createTheme',
path: 'packages/mui-material/build/styles/createTheme.js',
Copy link
Member Author

@Janpot Janpot Aug 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This import will be disallowed in ESM so I'm adding the possibility to import a specific export createTheme from @mui/material/styles instead.

It resulted in a slight decrease, but I'd consider it to be more accurate

importName: 'createTheme',
import: '@mui/material/styles',
},
{
id: 'colorManipulator',
path: 'packages/mui-system/build/colorManipulator/index.js',
import: '@mui/system/colorManipulator',
},
{
id: 'useAutocomplete',
path: 'packages/mui-lab/build/useAutocomplete/index.js',
import: '@mui/lab/useAutocomplete',
},
{
id: '@material-ui/core/useMediaQuery',
path: 'packages/mui-material/build/useMediaQuery/index.js',
import: '@mui/material/useMediaQuery',
},
{
id: '@material-ui/core/useScrollTrigger',
path: 'packages/mui-material/build/useScrollTrigger/index.js',
import: '@mui/material/useScrollTrigger',
},
{
id: '@material-ui/unstyled',
path: path.join(path.relative(workspaceRoot, corePackagePath), 'index.js'),
import: '@mui/base',
},
...coreComponents,
...baseComponents,
{
id: '@material-ui/utils',
path: 'packages/mui-utils/build/esm/index.js',
import: '@mui/utils',
},
// TODO: Requires webpack v5
// Resolution of webpack/acorn to 7.x is blocked by nextjs (https://github.com/vercel/next.js/issues/11947)
Expand All @@ -138,7 +139,7 @@ async function getWebpackEntries() {
// },
{
id: '@mui/joy',
path: path.join(path.relative(workspaceRoot, joyPackagePath), 'index.js'),
import: '@mui/joy',
},
...joyComponents,
];
Expand All @@ -148,6 +149,8 @@ function createWebpackConfig(entry, environment) {
const analyzerMode = environment.analyze ? 'static' : 'disabled';
const concatenateModules = !environment.accurateBundles;

const importNames = entry.importName ? `{ ${entry.importName} as foo }` : '* as foo';

/**
* @type {import('webpack').Configuration}
*/
Expand All @@ -160,7 +163,7 @@ function createWebpackConfig(entry, environment) {
concatenateModules,
minimizer: [
new TerserPlugin({
test: /\.js(\?.*)?$/i,
test: /\.m?js(\?.*)?$/i,
}),
],
},
Expand All @@ -174,6 +177,11 @@ function createWebpackConfig(entry, environment) {
},
path: path.join(__dirname, 'build'),
},
resolve: {
alias: {
'@mui/utils': '@mui/utils/esm',
},
},
plugins: [
new CompressionPlugin(),
new BundleAnalyzerPlugin({
Expand All @@ -186,7 +194,14 @@ function createWebpackConfig(entry, environment) {
reportFilename: `${entry.id}.html`,
}),
],
entry: { [entry.id]: path.join(workspaceRoot, entry.path) },
// A context to the current dir, which has a node_modules folder with workspace dependencies
context: __dirname,
entry: {
// This format is a data: url combined with inline matchResource to obtain a virtual entry.
// See https://github.com/webpack/webpack/issues/6437#issuecomment-874466638
// See https://webpack.js.org/api/loaders/#inline-matchresource
[entry.id]: `./index.js!=!data:text/javascript,import ${importNames} from '${entry.import}';console.log(foo);`,
Copy link
Member Author

@Janpot Janpot Aug 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the magic sauce:

  • context to current dir, this is where modules are resolved form. Now that it's a workspace, it has a node_modules folder.
  • data url, virtual file ./index.js which just imports the measured module. and logs to circumvent tree shaking

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO this deserves a comment in code. I don't think this syntax is widely known (I just learned about this and it's pretty hard to search for it).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, I've added some links in a comment

},
// TODO: 'browserslist:modern'
// See https://github.com/webpack/webpack/issues/14203
target: 'web',
Expand Down