Skip to content

Commit 9816548

Browse files
authored
[core] Improve tree-shakeability (#13391)
* [core] Add full esmodules build * [core] Add support for yarn workspaces run * Revert "[core] Add support for yarn workspaces run" This reverts commit e5653d7. * [core] Update size-limit * [core] esnext -> es * [core] Fix incorrect bundle sizes from merge * [core] Normalize build process * [core] sort scripts alphanumberic * [core] Add size test for esm build * [core] Fix unresolved module entry * [core] revert size limit changes for cjs build * [core] Fix increased size limit * [core] update size limits * [core] Normalize build scripts in icons and docs * fix size limit * fix utils build * [docs] fix build * [core] Reduce size tolerance * [core] Remove unnecessary array spread
1 parent ced9848 commit 9816548

File tree

15 files changed

+160
-94
lines changed

15 files changed

+160
-94
lines changed

.size-limit.js

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,17 @@ module.exports = [
1818
path: 'packages/material-ui/build/Paper/index.js',
1919
limit: '18.8 KB',
2020
},
21+
{
22+
name: 'The initial cost paid for using one component with ES modules',
23+
webpack: true,
24+
path: 'packages/material-ui/build/esm/Paper/index.js',
25+
limit: '17.9 KB',
26+
},
2127
{
2228
name: 'The size of the @material-ui/core modules',
2329
webpack: true,
2430
path: 'packages/material-ui/build/index.js',
25-
limit: '94.6 KB',
31+
limit: '91.2 KB',
2632
},
2733
{
2834
name: 'The size of the @material-ui/styles modules',
@@ -43,24 +49,25 @@ module.exports = [
4349
limit: '900 B',
4450
},
4551
{
52+
// why we use esm here: https://github.com/mui-org/material-ui/pull/13391#issuecomment-459692816
4653
name: 'The size of the @material-ui/core/Button component',
4754
webpack: true,
48-
path: 'packages/material-ui/build/Button/index.js',
49-
limit: '26.7 KB',
55+
path: 'packages/material-ui/build/esm/Button/index.js',
56+
limit: '24.6 KB',
5057
},
5158
{
5259
// vs https://bundlephobia.com/result?p=react-modal
5360
name: 'The size of the @material-ui/core/Modal component',
5461
webpack: true,
55-
path: 'packages/material-ui/build/Modal/index.js',
56-
limit: '26.4 KB',
62+
path: 'packages/material-ui/build/esm/Modal/index.js',
63+
limit: '24.1 KB',
5764
},
5865
{
5966
// vs https://bundlephobia.com/result?p=react-popper
6067
name: 'The size of the @material-ui/core/Popper component',
6168
webpack: true,
62-
path: 'packages/material-ui/build/Popper/index.js',
63-
limit: '10.8 KB',
69+
path: 'packages/material-ui/build/esm/Popper/index.js',
70+
limit: '9.7 KB',
6471
},
6572
{
6673
// vs https://bundlephobia.com/result?p=react-responsive
@@ -80,6 +87,6 @@ module.exports = [
8087
name: 'The docs home page',
8188
webpack: false,
8289
path: `.next/static/${buildId}/pages/index.js`,
83-
limit: '7 KB',
90+
limit: '6.2 KB',
8491
},
8592
];

babel.config.js

Lines changed: 27 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ if (process.env.BABEL_ENV === 'es') {
2121
[
2222
'@babel/preset-env',
2323
{
24-
modules: ['modules', 'production-umd'].includes(process.env.BABEL_ENV) ? false : 'commonjs',
24+
modules: ['esm', 'production-umd'].includes(process.env.BABEL_ENV) ? false : 'commonjs',
2525
},
2626
],
2727
];
@@ -36,6 +36,18 @@ const defaultAlias = {
3636
'@material-ui/system': './packages/material-ui-system/src',
3737
};
3838

39+
const productionPlugins = [
40+
'transform-react-constant-elements',
41+
'transform-dev-warning',
42+
['react-remove-properties', { properties: ['data-mui-test'] }],
43+
[
44+
'transform-react-remove-prop-types',
45+
{
46+
mode: 'unsafe-wrap',
47+
},
48+
],
49+
];
50+
3951
module.exports = {
4052
presets: defaultPresets.concat(['@babel/preset-react']),
4153
plugins: [
@@ -46,17 +58,8 @@ module.exports = {
4658
],
4759
ignore: [/@babel[\\|/]runtime/],
4860
env: {
49-
test: {
50-
sourceMaps: 'both',
51-
plugins: [
52-
[
53-
'babel-plugin-module-resolver',
54-
{
55-
root: ['./'],
56-
alias: defaultAlias,
57-
},
58-
],
59-
],
61+
cjs: {
62+
plugins: productionPlugins,
6063
},
6164
coverage: {
6265
plugins: [
@@ -124,47 +127,26 @@ module.exports = {
124127
['transform-react-remove-prop-types', { mode: 'remove' }],
125128
],
126129
},
130+
esm: {
131+
plugins: productionPlugins,
132+
},
127133
es: {
128-
plugins: [
129-
'transform-react-constant-elements',
130-
'transform-dev-warning',
131-
['react-remove-properties', { properties: ['data-mui-test'] }],
132-
[
133-
'transform-react-remove-prop-types',
134-
{
135-
mode: 'unsafe-wrap',
136-
},
137-
],
138-
],
139-
// It's most likely a babel bug.
140-
// We are using this ignore option in the CLI command but that has no effect.
141-
ignore: ['**/*.test.js'],
134+
plugins: productionPlugins,
142135
},
143136
production: {
144-
plugins: [
145-
'transform-react-constant-elements',
146-
'transform-dev-warning',
147-
['react-remove-properties', { properties: ['data-mui-test'] }],
148-
[
149-
'transform-react-remove-prop-types',
150-
{
151-
mode: 'unsafe-wrap',
152-
},
153-
],
154-
],
155-
// It's most likely a babel bug.
156-
// We are using this ignore option in the CLI command but that has no effect.
157-
ignore: ['**/*.test.js'],
137+
plugins: productionPlugins,
158138
},
159139
'production-umd': {
140+
plugins: productionPlugins,
141+
},
142+
test: {
143+
sourceMaps: 'both',
160144
plugins: [
161-
'transform-react-constant-elements',
162-
'transform-dev-warning',
163-
['react-remove-properties', { properties: ['data-mui-test'] }],
164145
[
165-
'transform-react-remove-prop-types',
146+
'babel-plugin-module-resolver',
166147
{
167-
mode: 'unsafe-wrap',
148+
root: ['./'],
149+
alias: defaultAlias,
168150
},
169151
],
170152
],

packages/material-ui-docs/package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@
2222
},
2323
"homepage": "https://github.com/mui-org/material-ui/tree/master/packages/material-ui-lab",
2424
"scripts": {
25-
"test": "exit 0",
26-
"prebuild": "rimraf build",
27-
"build:es2015": "cross-env NODE_ENV=production babel --config-file ../../babel.config.js ./src --out-dir ./build",
28-
"build:es2015modules": "cross-env NODE_ENV=production BABEL_ENV=modules babel --config-file ../../babel.config.js ./src/index.js --out-file ./build/index.es.js",
25+
"build": "yarn build:cjs && yarn build:esm && yarn build:copy-files",
26+
"build:cjs": "cross-env NODE_ENV=production BABEL_ENV=cjs babel --config-file ../../babel.config.js ./src --out-dir ./build --ignore \"**/*.test.js\"",
27+
"build:esm": "cross-env NODE_ENV=production BABEL_ENV=esm babel --config-file ../../babel.config.js ./src --out-dir ./build/esm --ignore \"**/*.test.js\"",
2928
"build:copy-files": "babel-node --config-file ../../babel.config.js ./scripts/copy-files.js",
30-
"build": "yarn build:es2015 && yarn build:es2015modules && yarn build:copy-files",
31-
"release": "yarn build && npm publish build"
29+
"prebuild": "rimraf build",
30+
"release": "yarn build && npm publish build",
31+
"test": "exit 0"
3232
},
3333
"peerDependencies": {
3434
"@material-ui/core": "^3.0.0",

packages/material-ui-docs/scripts/copy-files.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ async function addLicense(packageData) {
3838
*/
3939
`;
4040
await Promise.all(
41-
['../build/index.js', '../build/index.es.js'].map(file =>
41+
['../build/index.js', '../build/esm/index.js'].map(file =>
4242
prepend(path.resolve(__dirname, file), license),
4343
),
4444
);

packages/material-ui-icons/package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,11 @@
2222
},
2323
"homepage": "https://github.com/mui-org/material-ui/tree/master/packages/material-ui-icons",
2424
"scripts": {
25-
"build": "yarn build:es2015 && yarn build:es2015modules && yarn build:typings && yarn build:copy-files",
25+
"build": "yarn build:cjs && yarn build:esm && yarn build:es && yarn build:typings && yarn build:copy-files",
26+
"build:cjs": "cross-env NODE_ENV=production BABEL_ENV=cjs babel --config-file ../../babel.config.js ./src --out-dir ./build --ignore \"**/*.test.js\"",
27+
"build:esm": "cross-env NODE_ENV=production BABEL_ENV=esm babel --config-file ../../babel.config.js ./src --out-dir ./build/esm --ignore \"**/*.test.js\"",
28+
"build:es": "cross-env NODE_ENV=production BABEL_ENV=es babel --config-file ../../babel.config.js ./src --out-dir ./build/es --ignore \"**/*.test.js\"",
2629
"build:copy-files": "babel-node --config-file ../../babel.config.js ./scripts/copy-files.js",
27-
"build:es2015": "cross-env NODE_ENV=production babel --config-file ../../babel.config.js ./src --out-dir ./build",
28-
"build:es2015modules": "cross-env NODE_ENV=production BABEL_ENV=modules babel --config-file ../../babel.config.js ./src/index.js --out-file ./build/index.es.js",
2930
"build:typings": "babel-node --config-file ../../babel.config.js ./scripts/create-typings.js",
3031
"prebuild": "rimraf material-design-icons && rimraf build",
3132
"release": "yarn build && npm publish build",

packages/material-ui-lab/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@
2222
},
2323
"homepage": "https://github.com/mui-org/material-ui/tree/master/packages/material-ui-lab",
2424
"scripts": {
25-
"build": "yarn build:es2015 && yarn build:es2015modules && yarn build:es && yarn build:copy-files",
25+
"build": "yarn build:cjs && yarn build:esm && yarn build:es && yarn build:copy-files",
26+
"build:cjs": "cross-env NODE_ENV=production BABEL_ENV=cjs babel --config-file ../../babel.config.js ./src --out-dir ./build --ignore \"**/*.test.js\"",
27+
"build:esm": "cross-env NODE_ENV=production BABEL_ENV=esm babel --config-file ../../babel.config.js ./src --out-dir ./build/esm --ignore \"**/*.test.js\"",
28+
"build:es": "cross-env NODE_ENV=production BABEL_ENV=es babel --config-file ../../babel.config.js ./src --out-dir ./build/es --ignore \"**/*.test.js\"",
2629
"build:copy-files": "babel-node --config-file ../../babel.config.js ./scripts/copy-files.js",
27-
"build:es": "cross-env NODE_ENV=production BABEL_ENV=es babel --config-file ../../babel.config.js ./src --out-dir ./build/es --ignore *.test.js",
28-
"build:es2015": "cross-env NODE_ENV=production babel --config-file ../../babel.config.js ./src --out-dir ./build --ignore *.test.js",
29-
"build:es2015modules": "cross-env NODE_ENV=production BABEL_ENV=modules babel --config-file ../../babel.config.js ./src/index.js --out-file ./build/index.es.js",
3030
"prebuild": "rimraf build",
3131
"release": "yarn build && npm publish build",
3232
"test": "cd ../../ && cross-env NODE_ENV=test mocha 'packages/material-ui-lab/**/*.test.js' --exclude '**/node_modules/**'",

packages/material-ui-lab/scripts/copy-files.js

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,39 @@ async function copyFile(file) {
1010
console.log(`Copied ${file} to ${buildPath}`);
1111
}
1212

13+
/**
14+
* Puts a package.json into every immediate child directory of rootDir.
15+
* That package.json contains information about esm for bundlers so that imports
16+
* like import Typography from '@material-ui/core/Typography' are tree-shakeable.
17+
*
18+
* It also tests that an this import can be used in typescript by checking
19+
* if an index.d.ts is present at that path.
20+
*
21+
* @param {string} rootDir
22+
*/
23+
function createModulePackages(srcDir, outDir) {
24+
const directoryPackages = glob.sync('*/index.js', { cwd: srcDir }).map(path.dirname);
25+
return Promise.all(
26+
directoryPackages.map(directoryPackage => {
27+
const packageJson = {
28+
sideEffects: false,
29+
module: path.join('..', 'esm', directoryPackage, 'index.js'),
30+
};
31+
const packageJsonPath = path.join(outDir, directoryPackage, 'package.json');
32+
33+
return Promise.all([
34+
fse.exists(path.join(outDir, directoryPackage, 'index.d.ts')),
35+
fse.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2)),
36+
]).then(([typingsExist]) => {
37+
if (!typingsExist) {
38+
return Promise.reject(new Error(`index.d.ts for ${directoryPackage} is missing`));
39+
}
40+
return Promise.resolve(packageJsonPath);
41+
});
42+
}),
43+
);
44+
}
45+
1346
function typescriptCopy(from, to) {
1447
const files = glob.sync('**/*.d.ts', { cwd: from });
1548
const cmds = files.map(file => fse.copy(path.resolve(from, file), path.resolve(to, file)));
@@ -22,7 +55,7 @@ async function createPackageFile() {
2255
const newPackageData = {
2356
...packageDataOther,
2457
main: './index.js',
25-
module: './index.es.js',
58+
module: './esm/index.js',
2659
private: false,
2760
typings: './index.d.ts',
2861
};
@@ -47,7 +80,7 @@ async function addLicense(packageData) {
4780
*/
4881
`;
4982
await Promise.all(
50-
['../build/index.js', '../build/index.es.js'].map(file =>
83+
['../build/index.js', '../build/esm/index.js'].map(file =>
5184
prepend(path.resolve(__dirname, file), license),
5285
),
5386
);
@@ -64,6 +97,11 @@ async function run() {
6497
typescriptCopy(from, path.resolve(__dirname, '../build')),
6598
typescriptCopy(from, path.resolve(__dirname, '../build/es')),
6699
]);
100+
101+
await createModulePackages(
102+
path.resolve(__dirname, '../src'),
103+
path.resolve(__dirname, '../build'),
104+
);
67105
}
68106

69107
run();

packages/material-ui-styles/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@
2222
},
2323
"homepage": "https://github.com/mui-org/material-ui/tree/master/packages/material-ui-styles",
2424
"scripts": {
25-
"build": "yarn build:es2015 && yarn build:es2015modules && yarn build:es && yarn build:copy-files",
25+
"build": "yarn build:cjs && yarn build:esm && yarn build:es && yarn build:copy-files",
26+
"build:cjs": "cross-env NODE_ENV=production BABEL_ENV=cjs babel --config-file ../../babel.config.js ./src --out-dir ./build --ignore \"**/*.test.js\"",
27+
"build:esm": "cross-env NODE_ENV=production BABEL_ENV=esm babel --config-file ../../babel.config.js ./src --out-dir ./build/esm --ignore \"**/*.test.js\"",
28+
"build:es": "cross-env NODE_ENV=production BABEL_ENV=es babel --config-file ../../babel.config.js ./src --out-dir ./build/es --ignore \"**/*.test.js\"",
2629
"build:copy-files": "babel-node --config-file ../../babel.config.js ./scripts/copy-files.js",
27-
"build:es": "cross-env NODE_ENV=production BABEL_ENV=es babel --config-file ../../babel.config.js ./src --out-dir ./build/es --ignore *.test.js",
28-
"build:es2015": "cross-env NODE_ENV=production babel --config-file ../../babel.config.js ./src --out-dir ./build --ignore *.test.js",
29-
"build:es2015modules": "cross-env NODE_ENV=production BABEL_ENV=modules babel --config-file ../../babel.config.js ./src/index.js --out-file ./build/index.es.js",
3030
"prebuild": "rimraf build",
3131
"release": "yarn build && npm publish build",
3232
"test": "cd ../../ && cross-env NODE_ENV=test mocha 'packages/material-ui-styles/**/*.test.js' --exclude '**/node_modules/**'",

packages/material-ui-styles/scripts/copy-files.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ async function createPackageFile() {
2222
const newPackageData = {
2323
...packageDataOther,
2424
main: './index.js',
25-
module: './index.es.js',
25+
module: './esm/index.js',
2626
private: false,
2727
typings: './index.d.ts',
2828
};
@@ -47,7 +47,7 @@ async function addLicense(packageData) {
4747
*/
4848
`;
4949
await Promise.all(
50-
['../build/index.js', '../build/index.es.js'].map(file =>
50+
['../build/index.js', '../build/esm/index.js'].map(file =>
5151
prepend(path.resolve(__dirname, file), license),
5252
),
5353
);

packages/material-ui-system/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@
2222
},
2323
"homepage": "https://github.com/mui-org/material-ui/tree/master/packages/material-ui-system",
2424
"scripts": {
25-
"build": "yarn build:es2015 && yarn build:es2015modules && yarn build:es && yarn build:copy-files",
25+
"build": "yarn build:cjs && yarn build:esm && yarn build:es && yarn build:copy-files",
26+
"build:cjs": "cross-env NODE_ENV=production BABEL_ENV=cjs babel --config-file ../../babel.config.js ./src --out-dir ./build --ignore \"**/*.test.js\"",
27+
"build:esm": "cross-env NODE_ENV=production BABEL_ENV=esm babel --config-file ../../babel.config.js ./src --out-dir ./build/esm --ignore \"**/*.test.js\"",
28+
"build:es": "cross-env NODE_ENV=production BABEL_ENV=es babel --config-file ../../babel.config.js ./src --out-dir ./build/es --ignore \"**/*.test.js\"",
2629
"build:copy-files": "babel-node --config-file ../../babel.config.js ./scripts/copy-files.js",
27-
"build:es": "cross-env NODE_ENV=production BABEL_ENV=es babel --config-file ../../babel.config.js ./src --out-dir ./build/es --ignore *.test.js",
28-
"build:es2015": "cross-env NODE_ENV=production babel --config-file ../../babel.config.js ./src --out-dir ./build --ignore *.test.js",
29-
"build:es2015modules": "cross-env NODE_ENV=production BABEL_ENV=modules babel --config-file ../../babel.config.js ./src/index.js --out-file ./build/index.es.js",
3030
"prebuild": "rimraf build",
3131
"release": "yarn build && npm publish build",
3232
"test": "cd ../../ && cross-env NODE_ENV=test mocha 'packages/material-ui-system/**/*.test.js' --exclude '**/node_modules/**'"

packages/material-ui-system/scripts/copy-files.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ async function createPackageFile() {
2222
const newPackageData = {
2323
...packageDataOther,
2424
main: './index.js',
25-
module: './index.es.js',
25+
module: './esm/index.js',
2626
private: false,
2727
};
2828
const buildPath = path.resolve(__dirname, '../build/package.json');
@@ -46,7 +46,7 @@ async function addLicense(packageData) {
4646
*/
4747
`;
4848
await Promise.all(
49-
['../build/index.js', '../build/index.es.js'].map(file =>
49+
['../build/index.js', '../build/esm/index.js'].map(file =>
5050
prepend(path.resolve(__dirname, file), license),
5151
),
5252
);

packages/material-ui-utils/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@
2222
},
2323
"homepage": "https://github.com/mui-org/material-ui/tree/master/packages/material-ui-utils",
2424
"scripts": {
25-
"build": "yarn build:es2015 && yarn build:es2015modules && yarn build:es && yarn build:copy-files",
25+
"build": "yarn build:cjs && yarn build:esm && yarn build:es && yarn build:copy-files",
26+
"build:cjs": "cross-env NODE_ENV=production BABEL_ENV=cjs babel --config-file ../../babel.config.js ./src --out-dir ./build --ignore \"**/*.test.js\"",
27+
"build:esm": "cross-env NODE_ENV=production BABEL_ENV=esm babel --config-file ../../babel.config.js ./src --out-dir ./build/esm --ignore \"**/*.test.js\"",
28+
"build:es": "cross-env NODE_ENV=production BABEL_ENV=es babel --config-file ../../babel.config.js ./src --out-dir ./build/es --ignore \"**/*.test.js\"",
2629
"build:copy-files": "babel-node --config-file ../../babel.config.js ./scripts/copy-files.js",
27-
"build:es": "cross-env NODE_ENV=production BABEL_ENV=es babel --config-file ../../babel.config.js ./src --out-dir ./build/es --ignore *.test.js",
28-
"build:es2015": "cross-env NODE_ENV=production babel --config-file ../../babel.config.js ./src --out-dir ./build --ignore *.test.js",
29-
"build:es2015modules": "cross-env NODE_ENV=production BABEL_ENV=modules babel --config-file ../../babel.config.js ./src/index.js --out-file ./build/index.es.js",
3030
"prebuild": "rimraf build",
3131
"release": "yarn build && npm publish build",
3232
"test": "cd ../../ && cross-env NODE_ENV=test mocha 'packages/material-ui-utils/**/*.test.js' --exclude '**/node_modules/**'"

packages/material-ui-utils/scripts/copy-files.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ async function createPackageFile() {
2222
const newPackageData = {
2323
...packageDataOther,
2424
main: './index.js',
25-
module: './index.es.js',
25+
module: './esm/index.js',
2626
private: false,
2727
};
2828
const buildPath = path.resolve(__dirname, '../build/package.json');
@@ -46,7 +46,7 @@ async function addLicense(packageData) {
4646
*/
4747
`;
4848
await Promise.all(
49-
['../build/index.js', '../build/index.es.js'].map(file =>
49+
['../build/index.js', '../esm/index.js'].map(file =>
5050
prepend(path.resolve(__dirname, file), license),
5151
),
5252
);

0 commit comments

Comments
 (0)