Skip to content

Commit

Permalink
[core] Improve tree-shakeability (#13391)
Browse files Browse the repository at this point in the history
* [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
  • Loading branch information
eps1lon authored Feb 3, 2019
1 parent ced9848 commit 9816548
Show file tree
Hide file tree
Showing 15 changed files with 160 additions and 94 deletions.
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',
},
{
// 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'],
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

0 comments on commit 9816548

Please sign in to comment.