Skip to content

[code-infra] Create bundle size package #45911

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

Open
wants to merge 23 commits into
base: master
Choose a base branch
from
Open
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
70 changes: 23 additions & 47 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -650,70 +650,46 @@ jobs:
environment:
DANGER_COMMAND: prepareBundleSizeReport
- setup_corepack

- run:
name: build @mui packages
command: pnpm lerna run --ignore @mui/icons-material --concurrency 6 --scope "@mui/*" build
- aws-cli/setup:
aws_access_key_id: $AWS_ACCESS_KEY_ID_ARTIFACTS
aws_secret_access_key: $AWS_SECRET_ACCESS_KEY_ARTIFACTS
region: ${AWS_REGION_ARTIFACTS}

- run:
name: create @mui/material canary distributable
name: create and upload a size snapshot
command: |
cd packages/mui-material/build
npm version 0.0.0-canary.${CIRCLE_SHA1} --no-git-tag-version
npm pack
mv mui-material-0.0.0-canary.${CIRCLE_SHA1}.tgz ../../../mui-material.tgz
export AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID_ARTIFACTS
export AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY_ARTIFACTS
export AWS_REGION=$AWS_REGION_ARTIFACTS
pnpm size:snapshot

# === LEGACY START ===
# remove once the UI can handle the new format
# persist size snapshot on S3
- when:
# don't run on PRs
condition:
not:
matches:
# "^pull/\d+" is not valid YAML
# "^pull/\\d+" matches neither 'pull/1' nor 'main'
# Note that we want to include 'pull/1', 'pull/1/head' and ''pull/1/merge'
pattern: '^pull/.+$'
value: << pipeline.git.branch >>
pattern: '.+'
value: '${CIRCLE_PULL_REQUEST}'
steps:
- aws-cli/setup:
aws_access_key_id: $AWS_ACCESS_KEY_ID_ARTIFACTS
aws_secret_access_key: $AWS_SECRET_ACCESS_KEY_ARTIFACTS
region: ${AWS_REGION_ARTIFACTS}
# Upload distributables to S3
- aws-s3/copy:
from: mui-material.tgz
arguments: --content-type application/json
from: size-snapshot.json
to: s3://mui-org-ci/artifacts/$CIRCLE_BRANCH/$CIRCLE_SHA1/
- store_artifacts:
path: mui-material.tgz
destination: mui-material.tgz
- run:
name: create a size snapshot
command: pnpm size:snapshot
# === LEGACY END ===

# Keep the artifact storage as a CircleCI artifact
- store_artifacts:
name: persist size snapshot as pipeline artifact
path: size-snapshot.json
destination: size-snapshot.json
- when:
# don't run on PRs
condition:
not:
matches:
# "^pull/\d+" is not valid YAML
# "^pull/\\d+" matches neither 'pull/1' nor 'main'
# Note that we want to include 'pull/1', 'pull/1/head' and ''pull/1/merge'
pattern: '^pull/.+$'
value: << pipeline.git.branch >>
steps:
- aws-cli/setup:
aws_access_key_id: $AWS_ACCESS_KEY_ID_ARTIFACTS
aws_secret_access_key: $AWS_SECRET_ACCESS_KEY_ARTIFACTS
region: ${AWS_REGION_ARTIFACTS}
# persist size snapshot on S3
- aws-s3/copy:
arguments: --content-type application/json
from: size-snapshot.json
to: s3://mui-org-ci/artifacts/$CIRCLE_BRANCH/$CIRCLE_SHA1/
# symlink size-snapshot to latest
- aws-s3/copy:
arguments: --content-type application/json
from: size-snapshot.json
to: s3://mui-org-ci/artifacts/$CIRCLE_BRANCH/latest/

- run:
name: Run danger on PRs
command: pnpm danger ci --fail-on-errors
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ dist
node_modules
package-lock.json
size-snapshot.json
bundle-sizes/
docs/public/static/blog/feed/*
# vale downloaded config
.github/styles/
Expand Down
38 changes: 38 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<!-- vale off -->

# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Commands

Always use `pnpm --filter <pkg> <cmd>` to run pnpm commands in package context.

- **Build**: `pnpm release:build` (builds all packages excluding docs). `pnpm --filter <pkg> build` for individual packages.
- **Lint**: `pnpm eslint` (with caching), `pnpm prettier` (changed files)
- **Test**: `pnpm test` (runs ESLint, TypeScript check, and unit tests)
- **Single Test**: `pnpm tc [test name]` (runs a specific test)
- **TypeScript**: `pnpm typescript` (type checking)

## Code Style

- Use Prettier for formatting (100 char width, single quotes, trailing commas)
- Prefer `function Component()` over `React.FC`
- Name render functions in `React.forwardRef` for devtools
- Follow TypeScript conventions in TYPESCRIPT_CONVENTION.md
- Component props interfaces should be exported with name `{ComponentName}Props`
- For styled components, follow naming pattern `{ComponentName}{Slot}`
- Use proper JSDoc comments for public API components

## Imports

- Import from workspace with direct imports (e.g., from '@mui/material')
- Import test utilities from @mui/internal-test-utils

## Whitelisted Domains

- mui.com
- github.com
- npmjs.com
- react.dev
- developer.mozilla.org
61 changes: 61 additions & 0 deletions bundle-size/bundle-size-checker.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* @file Configuration file for bundle-size-checker
*
* This file determines which packages and components will have their bundle sizes measured.
*/
import path from 'path';
import glob from 'fast-glob';
import { defineConfig } from '@mui/internal-bundle-size-checker';

const rootDir = path.resolve(import.meta.dirname, '..');

/**
* Generates the entrypoints configuration by scanning the project structure.
*/
export default defineConfig(async () => {
// Discover Material UI components
const materialPackagePath = path.join(rootDir, 'packages/mui-material/build');
const materialFiles = await glob(path.join(materialPackagePath, '([A-Z])*/index.js'));
const materialComponents = materialFiles.map((componentPath) => {
const componentName = path.basename(path.dirname(componentPath));
return `@mui/material/${componentName}`;
});

// Discover Lab components
const labPackagePath = path.join(rootDir, 'packages/mui-lab/build');
const labFiles = await glob(path.join(labPackagePath, '([A-Z])*/index.js'));
const labComponents = labFiles.map((componentPath) => {
const componentName = path.basename(path.dirname(componentPath));
return `@mui/lab/${componentName}`;
});

const isPullRequest = !!process.env.CIRCLE_PULL_REQUEST;

// Return the complete entrypoints configuration
return {
entrypoints: [
'@mui/material',
...materialComponents,
'@mui/lab',
...labComponents,
'@mui/private-theming',
'@mui/system',
'@mui/system/createBox',
'@mui/system/createStyled',
'@mui/material/styles#createTheme',
'@mui/system/colorManipulator',
'@mui/lab/useAutocomplete',
'@mui/material/useMediaQuery',
'@mui/material/useScrollTrigger',
'@mui/utils',
],
// Only add upload config when in CI environment
...(process.env.CI && {
upload: {
project: 'mui/material-ui',
branch: process.env.CIRCLE_BRANCH,
isPullRequest,
},
}),
};
});
21 changes: 21 additions & 0 deletions bundle-size/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "@mui/bundle-size",
"version": "1.0.0",
"private": true,
"description": "Bundle size measurement workspace for MUI packages",
"scripts": {
"check": "NODE_OPTIONS=\"--max-old-space-size=4096\" bundle-size-checker --output ../size-snapshot.json"
},
"devDependencies": {
"@mui/bundle-size-checker": "github:mui/mui-public#bundle-size-checker&path:./packages/bundle-size-checker",
"fast-glob": "^3.3.2",
"path": "^0.12.7"
},
"dependencies": {
"@mui/material": "workspace:*",
"@mui/lab": "workspace:*",
"@mui/private-theming": "workspace:*",
"@mui/system": "workspace:*",
"@mui/utils": "workspace:*"
}
}
Loading
Loading