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] Update package layout for better ESM support #43264

Open
wants to merge 97 commits into
base: master
Choose a base branch
from

Conversation

Janpot
Copy link
Member

@Janpot Janpot commented Aug 11, 2024

addresses #44055
addresses #43980
addresses #44265
addresses #44180
addresses #44993
addresses #45018

Might close:

Add a new mode to the build:

  • Removes nested package.json files
  • Stores ESM files in esm subfolder with type:'module' in a package.json
  • Add exports field to package.json
  • Modern builds go in modern subfolder

Notes:

To Do:

Bundle size increase

The bundle size increase can be fully attributed to the inclusion of the following ESM/CJS interop helper in the webpack output:

Code
/******/ 	/* webpack/runtime/create fake namespace object */
/******/ 	(() => {
/******/ 		var getProto = Object.getPrototypeOf ? (obj) => (Object.getPrototypeOf(obj)) : (obj) => (obj.__proto__);
/******/ 		var leafPrototypes;
/******/ 		// create a fake namespace object
/******/ 		// mode & 1: value is a module id, require it
/******/ 		// mode & 2: merge all properties of value into the ns
/******/ 		// mode & 4: return value when already ns object
/******/ 		// mode & 16: return value when it's Promise-like
/******/ 		// mode & 8|1: behave like require
/******/ 		__webpack_require__.t = function(value, mode) {
/******/ 			if(mode & 1) value = this(value);
/******/ 			if(mode & 8) return value;
/******/ 			if(typeof value === 'object' && value) {
/******/ 				if((mode & 4) && value.__esModule) return value;
/******/ 				if((mode & 16) && typeof value.then === 'function') return value;
/******/ 			}
/******/ 			var ns = Object.create(null);
/******/ 			__webpack_require__.r(ns);
/******/ 			var def = {};
/******/ 			leafPrototypes = leafPrototypes || [null, getProto({}), getProto([]), getProto(getProto)];
/******/ 			for(var current = mode & 2 && value; typeof current == 'object' && !~leafPrototypes.indexOf(current); current = getProto(current)) {
/******/ 				Object.getOwnPropertyNames(current).forEach((key) => (def[key] = () => (value[key])));
/******/ 			}
/******/ 			def['default'] = () => (value);
/******/ 			__webpack_require__.d(ns, def);
/******/ 			return ns;
/******/ 		};
/******/ 	})();

This is caused by the following import

const maybeReactUseSyncExternalStore: undefined | any = (React as any)['useSyncExternalStore' + ''];

A potential switch to using use-sync-external-store has been explored in #43476 but ultimately it makes sense to keep it, it manifests in the webpack runtime.

Resolutions

To try out the changes use following resolutions:

"resolutions": {
    "@mui/internal-markdown": "https://pkg.csb.dev/mui/material-ui/commit/56c2982a/@mui/internal-markdown",
    "@mui/base": "https://pkg.csb.dev/mui/material-ui/commit/56c2982a/@mui/base",
    "@mui/codemod": "https://pkg.csb.dev/mui/material-ui/commit/56c2982a/@mui/codemod",
    "@mui/core-downloads-tracker": "https://pkg.csb.dev/mui/material-ui/commit/56c2982a/@mui/core-downloads-tracker",
    "@mui/docs": "https://pkg.csb.dev/mui/material-ui/commit/56c2982a/@mui/docs",
    "@mui/icons-material": "https://pkg.csb.dev/mui/material-ui/commit/56c2982a/@mui/icons-material",
    "@mui/lab": "https://pkg.csb.dev/mui/material-ui/commit/56c2982a/@mui/lab",
    "@mui/material-nextjs": "https://pkg.csb.dev/mui/material-ui/commit/56c2982a/@mui/material-nextjs",
    "@mui/material": "https://pkg.csb.dev/mui/material-ui/commit/56c2982a/@mui/material",
    "@mui/material-pigment-css": "https://pkg.csb.dev/mui/material-ui/commit/56c2982a/@mui/material-pigment-css",
    "@mui/private-theming": "https://pkg.csb.dev/mui/material-ui/commit/56c2982a/@mui/private-theming",
    "@mui/styled-engine-sc": "https://pkg.csb.dev/mui/material-ui/commit/56c2982a/@mui/styled-engine-sc",
    "@mui/styled-engine": "https://pkg.csb.dev/mui/material-ui/commit/56c2982a/@mui/styled-engine",
    "@mui/styles": "https://pkg.csb.dev/mui/material-ui/commit/56c2982a/@mui/styles",
    "@mui/system": "https://pkg.csb.dev/mui/material-ui/commit/56c2982a/@mui/system",
    "@mui/types": "https://pkg.csb.dev/mui/material-ui/commit/56c2982a/@mui/types",
    "@mui/utils": "https://pkg.csb.dev/mui/material-ui/commit/56c2982a/@mui/utils",
    "@mui/internal-babel-plugin-resolve-imports": "https://pkg.csb.dev/mui/material-ui/commit/56c2982a/@mui/internal-babel-plugin-resolve-imports",
    "@mui/internal-docs-utils": "https://pkg.csb.dev/mui/material-ui/commit/56c2982a/@mui/internal-docs-utils",
    "@mui/internal-scripts": "https://pkg.csb.dev/mui/material-ui/commit/56c2982a/@mui/internal-scripts",
    "@mui/internal-test-utils": "https://pkg.csb.dev/mui/material-ui/commit/56c2982a/@mui/internal-test-utils",
    "@mui/x-license": "https://pkg.csb.dev/mui/mui-x/commit/ffb75046/@mui/x-license",
    "@mui/x-data-grid": "https://pkg.csb.dev/mui/mui-x/commit/ffb75046/@mui/x-data-grid",
    "@mui/x-data-grid-pro": "https://pkg.csb.dev/mui/mui-x/commit/ffb75046/@mui/x-data-grid-pro",
    "@mui/x-data-grid-premium": "https://pkg.csb.dev/mui/mui-x/commit/ffb75046/@mui/x-data-grid-premium",
    "@mui/x-data-grid-generator": "https://pkg.csb.dev/mui/mui-x/commit/ffb75046/@mui/x-data-grid-generator",
    "@mui/x-date-pickers": "https://pkg.csb.dev/mui/mui-x/commit/ffb75046/@mui/x-date-pickers",
    "@mui/x-date-pickers-pro": "https://pkg.csb.dev/mui/mui-x/commit/ffb75046/@mui/x-date-pickers-pro",
    "@mui/x-charts": "https://pkg.csb.dev/mui/mui-x/commit/ffb75046/@mui/x-charts",
    "@mui/x-charts-pro": "https://pkg.csb.dev/mui/mui-x/commit/ffb75046/@mui/x-charts-pro",
    "@mui/x-charts-vendor": "https://pkg.csb.dev/mui/mui-x/commit/ffb75046/@mui/x-charts-vendor",
    "@mui/x-tree-view": "https://pkg.csb.dev/mui/mui-x/commit/ffb75046/@mui/x-tree-view",
    "@mui/x-tree-view-pro": "https://pkg.csb.dev/mui/mui-x/commit/ffb75046/@mui/x-tree-view-pro",
    "@mui/x-internals": "https://pkg.csb.dev/mui/mui-x/commit/ffb75046/@mui/x-internals"
  },

@Janpot Janpot added the scope: code-infra Specific to the core-infra product label Aug 11, 2024
@Janpot Janpot changed the title [core] Try new build mode that creates package exports [core] Update package layout for better ESM support Aug 11, 2024
@mui-bot
Copy link

mui-bot commented Aug 11, 2024

Netlify deploy preview

https://deploy-preview-43264--material-ui.netlify.app/

Menu: parsed: +3.73% , gzip: +3.83%
@material-ui/unstyled: parsed: +0.92% , gzip: +1.01%
Select: parsed: +3.16% , gzip: +3.17%
Unstable_Popup: parsed: +3.05% , gzip: +2.63%
Unstable_NumberInput: parsed: +5.11% , gzip: +5.90%
@material-ui/core/useMediaQuery: parsed: +5.09% , gzip: +4.53%
MenuItem: parsed: +6.67% , gzip: +6.83%
Option: parsed: +6.97% , gzip: +7.37%
Tab: parsed: +7.47% , gzip: +7.53%
TabPanel: parsed: +12.28% , gzip: +11.45%
useAutocomplete: parsed: +5.06% , gzip: +5.47%
TablePagination: parsed: +7.54% , gzip: +8.23%
Tooltip: parsed: +0.44% , gzip: +0.48%
SpeedDialAction: parsed: +0.37% , gzip: +0.40%
@mui/joy/Menu: parsed: +0.41% , gzip: +0.50%
TextField: parsed: +0.34% , gzip: +0.31%
@mui/joy/Tooltip: parsed: +0.52% , gzip: +0.51%
RadioGroup: parsed: +0.68% , gzip: +0.73%
@mui/joy/ListSubheader: parsed: +0.77% , gzip: +0.72%
LoadingButton: parsed: +0.51% , gzip: +0.49%
and 27 more changes

Bundle size report

Details of bundle changes (Toolpad)
Details of bundle changes

Generated by 🚫 dangerJS against 6cdfa8c

@Janpot Janpot changed the title [core] Update package layout for better ESM support [code-infra] Update package layout for better ESM support Aug 12, 2024
@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged label Aug 12, 2024
@github-actions github-actions bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged label Aug 23, 2024
@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged label Jan 20, 2025
@github-actions github-actions bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged label Jan 23, 2025
Copy link
Member

@DiegoAndai DiegoAndai left a comment

Choose a reason for hiding this comment

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

A couple of questions:

  • Why create a subfolder for ESM, instead of maintaining the current convention where the subfolder is for CJS and ESM is at the root?
  • Can (should) we create tests for the package layout/build process? To ensure, for example, that the ATTW check is not broken, or that the package layout is not changed unknowingly.

package.json Outdated Show resolved Hide resolved
packages/mui-base/src/Select/Select.test.tsx Show resolved Hide resolved
packages/mui-icons-material/package.json Outdated Show resolved Hide resolved
scripts/build.mjs Show resolved Hide resolved
scripts/copyFilesUtils.mjs Show resolved Hide resolved
@Janpot
Copy link
Member Author

Janpot commented Jan 24, 2025

  • Why create a subfolder for ESM, instead of maintaining the current convention where the subfolder is for CJS and ESM is at the root?

To be able to mark all .js files in esm/ as ESM with a package.json containing type: 'module'. It's interesting to be able to keep the .js extension because that means we can just copy the typings from one folder to the other. Also to keep some parity with base UI.

  • Can (should) we create tests for the package layout/build process? To ensure, for example, that the ATTW check is not broken, or that the package layout is not changed unknowingly.

I also fixed up the existing bundler tests and added an extra case for the next.js issue we saw.

@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged label Jan 27, 2025
@DiegoAndai
Copy link
Member

Thanks for replying to my questions @Janpot. Everything looks good from my side. Feel free to mark this as ready for review whenever you're ready.

@github-actions github-actions bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged label Jan 28, 2025
@Janpot
Copy link
Member Author

Janpot commented Jan 28, 2025

@DiegoAndai Only problem left seems to be that the github action that builds @apps/next-app has become a lot heavier on macos. It takes about twice the time to run in CI, locally it runs out of memory for me (have to use NODE_OPTIONS="--max-old-space-size=8192"). windows/linux seem to be fine. cc @brijeshb42 in case you have an idea?

@Janpot Janpot marked this pull request as ready for review January 28, 2025 10:32
@brijeshb42
Copy link
Contributor

What we can do is disable this app temporarily in this repo and move it to Pigment where I can take a look later to unblock.

@DiegoAndai
Copy link
Member

What we can do is disable this app temporarily in this repo and move it to Pigment where I can take a look later to unblock.

I think it would be better first to investigate if this is due to the next-app's specific config or if this would impact everyone using next with this updated package layout.

So, there is no rush to take it out now, but let's work together to find the root cause.

@brijeshb42
Copy link
Contributor

brijeshb42 commented Jan 28, 2025

What's the average build time on master/other PRs ?

Let me check this locally.

@DiegoAndai
Copy link
Member

What's the average build time on master/other PRs ?

I don't have the specifics for the next-app, but:

The last 5 master test-dev (macos) builds (pnpm build:ci) took between 4 and 7 minutes

The last one on this PR was over 2 hours, the one before that was 14 minutes.

There's definitely something going on.

@brijeshb42
Copy link
Contributor

Just checked locally on both master and ^ this branch. master built in 2 mins but this branch's build failed with some heap memory error.
I'll have to bisect commit by commit to identify the issue. I'll update once I have some result.

@brijeshb42
Copy link
Contributor

brijeshb42 commented Jan 29, 2025

@Janpot what was the issue?

@Janpot
Copy link
Member Author

Janpot commented Jan 29, 2025

It's not solved yet, this action just took 1 hour to run.

@Janpot
Copy link
Member Author

Janpot commented Jan 30, 2025

I think it would be better first to investigate if this is due to the next-app's specific config or if this would impact everyone using next with this updated package layout.

I tried removing pigment from the app, but kept as much as possible of the original pages and it reduces runtime drastically, see https://github.com/mui/material-ui/actions/runs/13055965609/job/36426957328?pr=45152
This suggests it's caused by some combination of pigment css with the new package layout. It's also almost 3 to 4 times faster than master, goes to show the overhead it could create.

@DiegoAndai
Copy link
Member

@Janpot which option should we follow:

  1. Investigate the issue before merging
  2. Remove the Pigment build and investigate separately

?

I worry that the increase in build time might uncover some edge cases with the new layout we haven't seen. But if you think it's more likely to be caused by Pigment's configuration, then we could unblock this and investigate separately. This would get the layout change to users faster, so we got feedback earlier.

This suggests it's caused by some combination of pigment css with the new package layout. It's also almost 3 to 4 times faster than master, goes to show the overhead it could create.

I didn't understand this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
scope: code-infra Specific to the core-infra product
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants