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

[core] Improve tree-shakeability #13391

Merged
merged 22 commits into from
Feb 3, 2019
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
23 changes: 15 additions & 8 deletions .size-limit.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,17 @@ module.exports = [
path: 'packages/material-ui/build/Paper/index.js',
limit: '18.8 KB',
},
{
name: 'The initial cost paid for using one component with ES modules',
webpack: true,
path: 'packages/material-ui/build/esm/Paper/index.js',
limit: '17.9 KB',
},
{
name: 'The size of the @material-ui/core modules',
webpack: true,
path: 'packages/material-ui/build/index.js',
limit: '94.6 KB',
limit: '91.2 KB',
},
{
name: 'The size of the @material-ui/styles modules',
Expand All @@ -43,24 +49,25 @@ module.exports = [
limit: '900 B',
},
{
// why we use esm here: https://github.com/mui-org/material-ui/pull/13391#issuecomment-459692816
name: 'The size of the @material-ui/core/Button component',
webpack: true,
path: 'packages/material-ui/build/Button/index.js',
limit: '26.7 KB',
path: 'packages/material-ui/build/esm/Button/index.js',
limit: '24.6 KB',
},
{
// vs https://bundlephobia.com/result?p=react-modal
name: 'The size of the @material-ui/core/Modal component',
webpack: true,
path: 'packages/material-ui/build/Modal/index.js',
limit: '26.4 KB',
path: 'packages/material-ui/build/esm/Modal/index.js',
limit: '24.1 KB',
Copy link
Member Author

Choose a reason for hiding this comment

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

tree-shaking-salesman

},
{
// vs https://bundlephobia.com/result?p=react-popper
name: 'The size of the @material-ui/core/Popper component',
webpack: true,
path: 'packages/material-ui/build/Popper/index.js',
limit: '10.8 KB',
path: 'packages/material-ui/build/esm/Popper/index.js',
limit: '9.7 KB',
},
{
// vs https://bundlephobia.com/result?p=react-responsive
Expand All @@ -80,6 +87,6 @@ module.exports = [
name: 'The docs home page',
webpack: false,
path: `.next/static/${buildId}/pages/index.js`,
limit: '7 KB',
limit: '6.2 KB',
},
];
72 changes: 27 additions & 45 deletions babel.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ if (process.env.BABEL_ENV === 'es') {
[
'@babel/preset-env',
{
modules: ['modules', 'production-umd'].includes(process.env.BABEL_ENV) ? false : 'commonjs',
modules: ['esm', 'production-umd'].includes(process.env.BABEL_ENV) ? false : 'commonjs',
},
],
];
Expand All @@ -36,6 +36,18 @@ const defaultAlias = {
'@material-ui/system': './packages/material-ui-system/src',
};

const productionPlugins = [
'transform-react-constant-elements',
'transform-dev-warning',
['react-remove-properties', { properties: ['data-mui-test'] }],
[
'transform-react-remove-prop-types',
{
mode: 'unsafe-wrap',
},
],
];

module.exports = {
presets: defaultPresets.concat(['@babel/preset-react']),
plugins: [
Expand All @@ -46,17 +58,8 @@ module.exports = {
],
ignore: [/@babel[\\|/]runtime/],
env: {
test: {
sourceMaps: 'both',
plugins: [
[
'babel-plugin-module-resolver',
{
root: ['./'],
alias: defaultAlias,
},
],
],
cjs: {
plugins: productionPlugins,
},
coverage: {
plugins: [
Expand Down Expand Up @@ -124,47 +127,26 @@ module.exports = {
['transform-react-remove-prop-types', { mode: 'remove' }],
],
},
esm: {
plugins: productionPlugins,
},
es: {
plugins: [
'transform-react-constant-elements',
'transform-dev-warning',
['react-remove-properties', { properties: ['data-mui-test'] }],
[
'transform-react-remove-prop-types',
{
mode: 'unsafe-wrap',
},
],
],
// It's most likely a babel bug.
// We are using this ignore option in the CLI command but that has no effect.
ignore: ['**/*.test.js'],
Copy link
Member Author

Choose a reason for hiding this comment

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

This was used in the cli with --ignore **/*.test.js. Most shells already expand those. If you want to pass a glob to a node script you have to escape it with ". I've made that mistake myself and it's quite common. Only prettier documents this well.

plugins: productionPlugins,
},
production: {
plugins: [
'transform-react-constant-elements',
'transform-dev-warning',
['react-remove-properties', { properties: ['data-mui-test'] }],
[
'transform-react-remove-prop-types',
{
mode: 'unsafe-wrap',
},
],
],
// It's most likely a babel bug.
// We are using this ignore option in the CLI command but that has no effect.
ignore: ['**/*.test.js'],
plugins: productionPlugins,
},
'production-umd': {
plugins: productionPlugins,
},
test: {
sourceMaps: 'both',
plugins: [
'transform-react-constant-elements',
'transform-dev-warning',
['react-remove-properties', { properties: ['data-mui-test'] }],
[
'transform-react-remove-prop-types',
'babel-plugin-module-resolver',
{
mode: 'unsafe-wrap',
root: ['./'],
alias: defaultAlias,
},
],
],
Expand Down
12 changes: 6 additions & 6 deletions packages/material-ui-docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@
},
"homepage": "https://github.com/mui-org/material-ui/tree/master/packages/material-ui-lab",
"scripts": {
"test": "exit 0",
"prebuild": "rimraf build",
"build:es2015": "cross-env NODE_ENV=production babel --config-file ../../babel.config.js ./src --out-dir ./build",
"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",
"build": "yarn build:cjs && yarn build:esm && yarn build:copy-files",
"build:cjs": "cross-env NODE_ENV=production BABEL_ENV=cjs babel --config-file ../../babel.config.js ./src --out-dir ./build --ignore \"**/*.test.js\"",
"build:esm": "cross-env NODE_ENV=production BABEL_ENV=esm babel --config-file ../../babel.config.js ./src --out-dir ./build/esm --ignore \"**/*.test.js\"",
"build:copy-files": "babel-node --config-file ../../babel.config.js ./scripts/copy-files.js",
"build": "yarn build:es2015 && yarn build:es2015modules && yarn build:copy-files",
"release": "yarn build && npm publish build"
"prebuild": "rimraf build",
"release": "yarn build && npm publish build",
"test": "exit 0"
},
"peerDependencies": {
"@material-ui/core": "^3.0.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/material-ui-docs/scripts/copy-files.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ async function addLicense(packageData) {
*/
`;
await Promise.all(
['../build/index.js', '../build/index.es.js'].map(file =>
['../build/index.js', '../build/esm/index.js'].map(file =>
prepend(path.resolve(__dirname, file), license),
),
);
Expand Down
7 changes: 4 additions & 3 deletions packages/material-ui-icons/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@
},
"homepage": "https://github.com/mui-org/material-ui/tree/master/packages/material-ui-icons",
"scripts": {
"build": "yarn build:es2015 && yarn build:es2015modules && yarn build:typings && yarn build:copy-files",
"build": "yarn build:cjs && yarn build:esm && yarn build:es && yarn build:typings && yarn build:copy-files",
"build:cjs": "cross-env NODE_ENV=production BABEL_ENV=cjs babel --config-file ../../babel.config.js ./src --out-dir ./build --ignore \"**/*.test.js\"",
"build:esm": "cross-env NODE_ENV=production BABEL_ENV=esm babel --config-file ../../babel.config.js ./src --out-dir ./build/esm --ignore \"**/*.test.js\"",
"build:es": "cross-env NODE_ENV=production BABEL_ENV=es babel --config-file ../../babel.config.js ./src --out-dir ./build/es --ignore \"**/*.test.js\"",
"build:copy-files": "babel-node --config-file ../../babel.config.js ./scripts/copy-files.js",
"build:es2015": "cross-env NODE_ENV=production babel --config-file ../../babel.config.js ./src --out-dir ./build",
"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",
"build:typings": "babel-node --config-file ../../babel.config.js ./scripts/create-typings.js",
"prebuild": "rimraf material-design-icons && rimraf build",
"release": "yarn build && npm publish build",
Expand Down
8 changes: 4 additions & 4 deletions packages/material-ui-lab/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@
},
"homepage": "https://github.com/mui-org/material-ui/tree/master/packages/material-ui-lab",
"scripts": {
"build": "yarn build:es2015 && yarn build:es2015modules && yarn build:es && yarn build:copy-files",
"build": "yarn build:cjs && yarn build:esm && yarn build:es && yarn build:copy-files",
"build:cjs": "cross-env NODE_ENV=production BABEL_ENV=cjs babel --config-file ../../babel.config.js ./src --out-dir ./build --ignore \"**/*.test.js\"",
"build:esm": "cross-env NODE_ENV=production BABEL_ENV=esm babel --config-file ../../babel.config.js ./src --out-dir ./build/esm --ignore \"**/*.test.js\"",
"build:es": "cross-env NODE_ENV=production BABEL_ENV=es babel --config-file ../../babel.config.js ./src --out-dir ./build/es --ignore \"**/*.test.js\"",
"build:copy-files": "babel-node --config-file ../../babel.config.js ./scripts/copy-files.js",
"build:es": "cross-env NODE_ENV=production BABEL_ENV=es babel --config-file ../../babel.config.js ./src --out-dir ./build/es --ignore *.test.js",
"build:es2015": "cross-env NODE_ENV=production babel --config-file ../../babel.config.js ./src --out-dir ./build --ignore *.test.js",
"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",
"prebuild": "rimraf build",
"release": "yarn build && npm publish build",
"test": "cd ../../ && cross-env NODE_ENV=test mocha 'packages/material-ui-lab/**/*.test.js' --exclude '**/node_modules/**'",
Expand Down
42 changes: 40 additions & 2 deletions packages/material-ui-lab/scripts/copy-files.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,39 @@ async function copyFile(file) {
console.log(`Copied ${file} to ${buildPath}`);
}

/**
* Puts a package.json into every immediate child directory of rootDir.
* That package.json contains information about esm for bundlers so that imports
* like import Typography from '@material-ui/core/Typography' are tree-shakeable.
*
* It also tests that an this import can be used in typescript by checking
* if an index.d.ts is present at that path.
*
* @param {string} rootDir
*/
function createModulePackages(srcDir, outDir) {
const directoryPackages = glob.sync('*/index.js', { cwd: srcDir }).map(path.dirname);
return Promise.all(
directoryPackages.map(directoryPackage => {
const packageJson = {
sideEffects: false,
module: path.join('..', 'esm', directoryPackage, 'index.js'),
};
const packageJsonPath = path.join(outDir, directoryPackage, 'package.json');

return Promise.all([
fse.exists(path.join(outDir, directoryPackage, 'index.d.ts')),
fse.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2)),
]).then(([typingsExist]) => {
if (!typingsExist) {
return Promise.reject(new Error(`index.d.ts for ${directoryPackage} is missing`));
}
return Promise.resolve(packageJsonPath);
});
}),
);
}

function typescriptCopy(from, to) {
const files = glob.sync('**/*.d.ts', { cwd: from });
const cmds = files.map(file => fse.copy(path.resolve(from, file), path.resolve(to, file)));
Expand All @@ -22,7 +55,7 @@ async function createPackageFile() {
const newPackageData = {
...packageDataOther,
main: './index.js',
module: './index.es.js',
module: './esm/index.js',
private: false,
typings: './index.d.ts',
};
Expand All @@ -47,7 +80,7 @@ async function addLicense(packageData) {
*/
`;
await Promise.all(
['../build/index.js', '../build/index.es.js'].map(file =>
['../build/index.js', '../build/esm/index.js'].map(file =>
prepend(path.resolve(__dirname, file), license),
),
);
Expand All @@ -64,6 +97,11 @@ async function run() {
typescriptCopy(from, path.resolve(__dirname, '../build')),
typescriptCopy(from, path.resolve(__dirname, '../build/es')),
]);

await createModulePackages(
path.resolve(__dirname, '../src'),
path.resolve(__dirname, '../build'),
);
}

run();
8 changes: 4 additions & 4 deletions packages/material-ui-styles/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@
},
"homepage": "https://github.com/mui-org/material-ui/tree/master/packages/material-ui-styles",
"scripts": {
"build": "yarn build:es2015 && yarn build:es2015modules && yarn build:es && yarn build:copy-files",
"build": "yarn build:cjs && yarn build:esm && yarn build:es && yarn build:copy-files",
"build:cjs": "cross-env NODE_ENV=production BABEL_ENV=cjs babel --config-file ../../babel.config.js ./src --out-dir ./build --ignore \"**/*.test.js\"",
"build:esm": "cross-env NODE_ENV=production BABEL_ENV=esm babel --config-file ../../babel.config.js ./src --out-dir ./build/esm --ignore \"**/*.test.js\"",
"build:es": "cross-env NODE_ENV=production BABEL_ENV=es babel --config-file ../../babel.config.js ./src --out-dir ./build/es --ignore \"**/*.test.js\"",
"build:copy-files": "babel-node --config-file ../../babel.config.js ./scripts/copy-files.js",
"build:es": "cross-env NODE_ENV=production BABEL_ENV=es babel --config-file ../../babel.config.js ./src --out-dir ./build/es --ignore *.test.js",
"build:es2015": "cross-env NODE_ENV=production babel --config-file ../../babel.config.js ./src --out-dir ./build --ignore *.test.js",
"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",
"prebuild": "rimraf build",
"release": "yarn build && npm publish build",
"test": "cd ../../ && cross-env NODE_ENV=test mocha 'packages/material-ui-styles/**/*.test.js' --exclude '**/node_modules/**'",
Expand Down
4 changes: 2 additions & 2 deletions packages/material-ui-styles/scripts/copy-files.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ async function createPackageFile() {
const newPackageData = {
...packageDataOther,
main: './index.js',
module: './index.es.js',
module: './esm/index.js',
private: false,
typings: './index.d.ts',
};
Expand All @@ -47,7 +47,7 @@ async function addLicense(packageData) {
*/
`;
await Promise.all(
['../build/index.js', '../build/index.es.js'].map(file =>
['../build/index.js', '../build/esm/index.js'].map(file =>
prepend(path.resolve(__dirname, file), license),
),
);
Expand Down
8 changes: 4 additions & 4 deletions packages/material-ui-system/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@
},
"homepage": "https://github.com/mui-org/material-ui/tree/master/packages/material-ui-system",
"scripts": {
"build": "yarn build:es2015 && yarn build:es2015modules && yarn build:es && yarn build:copy-files",
"build": "yarn build:cjs && yarn build:esm && yarn build:es && yarn build:copy-files",
"build:cjs": "cross-env NODE_ENV=production BABEL_ENV=cjs babel --config-file ../../babel.config.js ./src --out-dir ./build --ignore \"**/*.test.js\"",
"build:esm": "cross-env NODE_ENV=production BABEL_ENV=esm babel --config-file ../../babel.config.js ./src --out-dir ./build/esm --ignore \"**/*.test.js\"",
"build:es": "cross-env NODE_ENV=production BABEL_ENV=es babel --config-file ../../babel.config.js ./src --out-dir ./build/es --ignore \"**/*.test.js\"",
"build:copy-files": "babel-node --config-file ../../babel.config.js ./scripts/copy-files.js",
"build:es": "cross-env NODE_ENV=production BABEL_ENV=es babel --config-file ../../babel.config.js ./src --out-dir ./build/es --ignore *.test.js",
"build:es2015": "cross-env NODE_ENV=production babel --config-file ../../babel.config.js ./src --out-dir ./build --ignore *.test.js",
"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",
"prebuild": "rimraf build",
"release": "yarn build && npm publish build",
"test": "cd ../../ && cross-env NODE_ENV=test mocha 'packages/material-ui-system/**/*.test.js' --exclude '**/node_modules/**'"
Expand Down
4 changes: 2 additions & 2 deletions packages/material-ui-system/scripts/copy-files.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ async function createPackageFile() {
const newPackageData = {
...packageDataOther,
main: './index.js',
module: './index.es.js',
module: './esm/index.js',
private: false,
};
const buildPath = path.resolve(__dirname, '../build/package.json');
Expand All @@ -46,7 +46,7 @@ async function addLicense(packageData) {
*/
`;
await Promise.all(
['../build/index.js', '../build/index.es.js'].map(file =>
['../build/index.js', '../build/esm/index.js'].map(file =>
prepend(path.resolve(__dirname, file), license),
),
);
Expand Down
8 changes: 4 additions & 4 deletions packages/material-ui-utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@
},
"homepage": "https://github.com/mui-org/material-ui/tree/master/packages/material-ui-utils",
"scripts": {
"build": "yarn build:es2015 && yarn build:es2015modules && yarn build:es && yarn build:copy-files",
"build": "yarn build:cjs && yarn build:esm && yarn build:es && yarn build:copy-files",
"build:cjs": "cross-env NODE_ENV=production BABEL_ENV=cjs babel --config-file ../../babel.config.js ./src --out-dir ./build --ignore \"**/*.test.js\"",
"build:esm": "cross-env NODE_ENV=production BABEL_ENV=esm babel --config-file ../../babel.config.js ./src --out-dir ./build/esm --ignore \"**/*.test.js\"",
"build:es": "cross-env NODE_ENV=production BABEL_ENV=es babel --config-file ../../babel.config.js ./src --out-dir ./build/es --ignore \"**/*.test.js\"",
"build:copy-files": "babel-node --config-file ../../babel.config.js ./scripts/copy-files.js",
"build:es": "cross-env NODE_ENV=production BABEL_ENV=es babel --config-file ../../babel.config.js ./src --out-dir ./build/es --ignore *.test.js",
"build:es2015": "cross-env NODE_ENV=production babel --config-file ../../babel.config.js ./src --out-dir ./build --ignore *.test.js",
"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",
"prebuild": "rimraf build",
"release": "yarn build && npm publish build",
"test": "cd ../../ && cross-env NODE_ENV=test mocha 'packages/material-ui-utils/**/*.test.js' --exclude '**/node_modules/**'"
Expand Down
4 changes: 2 additions & 2 deletions packages/material-ui-utils/scripts/copy-files.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ async function createPackageFile() {
const newPackageData = {
...packageDataOther,
main: './index.js',
module: './index.es.js',
module: './esm/index.js',
private: false,
};
const buildPath = path.resolve(__dirname, '../build/package.json');
Expand All @@ -46,7 +46,7 @@ async function addLicense(packageData) {
*/
`;
await Promise.all(
['../build/index.js', '../build/index.es.js'].map(file =>
['../build/index.js', '../esm/index.js'].map(file =>
prepend(path.resolve(__dirname, file), license),
),
);
Expand Down
Loading