diff --git a/docs/src/pages/guides/minimizing-bundle-size/minimizing-bundle-size.md b/docs/src/pages/guides/minimizing-bundle-size/minimizing-bundle-size.md index 5ffd41e43f1973..be97d7d12d6ea3 100644 --- a/docs/src/pages/guides/minimizing-bundle-size/minimizing-bundle-size.md +++ b/docs/src/pages/guides/minimizing-bundle-size/minimizing-bundle-size.md @@ -19,9 +19,9 @@ use named imports and expect only a minimal set of Material-UI components in you import { Button, TextField } from '@material-ui/core'; ``` -Be aware that tree-shaking is an optimization that is usually only applied to production -bundles. Development bundles will contain the full library which can lead to slower -startup times. This is especially noticeable if you import from `@material-ui/icons`. +⚠️ Be aware that tree-shaking is an optimization that is usually only applied to production +bundles. Development bundles will contain the full library which can lead to **slower +startup times**. This is especially noticeable if you import from `@material-ui/icons`. Startup times can be approximately 6x slower than without named imports from the top-level API. If this is an issue for you, you have various options: @@ -37,66 +37,100 @@ import { Button, TextField } from '@material-ui/core'; use: ```js +// 🚀 Fast import Button from '@material-ui/core/Button'; import TextField from '@material-ui/core/TextField'; ``` +This is the option we document in **all** the demos as the one that requires no configuration. Head to [Option 2](#option-2) for the option we recommend. + While importing directly in this manner doesn't use the exports in [`@material-ui/core/index.js`](https://github.com/mui-org/material-ui/blob/master/packages/material-ui/src/index.js), this file can serve as a handy reference as to which modules are public. Be aware that we only support first and second level imports. Anything below is considered private and can cause module duplication in your bundle. ```js -// OK +// ✅ OK import { Add as AddIcon } from '@material-ui/icons'; import { Tabs } from '@material-ui/core'; // ^^^^ 1st or top-level -// OK +// ✅ OK import AddIcon from '@material-ui/icons/Add'; import Tabs from '@material-ui/core/Tabs'; // ^^^^ 2nd level -// NOT OK +// ❌ NOT OK import TabIndicator from '@material-ui/core/Tabs/TabIndicator'; // ^^^^^^^^^^^^ 3rd level ``` ### Option 2 -**Important note**: This is only supported for `@material-ui/icons`. -We recommend this approach if you often restart your development build. +We **recommend** this option as providing the best DX and UX. +However, you need to apply the following steps correctly. -Another option is to keep using named imports, but still have shorter -start up times by using `babel` plugins. +#### 1. Configure Babel Pick one of the following plugins: - [babel-plugin-import](https://github.com/ant-design/babel-plugin-import) with the following configuration: + ```js - [ - 'babel-plugin-import', - { - libraryName: '@material-ui/icons', - libraryDirectory: 'esm', // or '' if your bundler does not support ES modules - camel2DashComponentName: false, - }, - ]; + plugins: [ + [ + 'babel-plugin-import', + { + libraryName: '@material-ui/core', + libraryDirectory: 'esm', // or '' if your bundler does not support ES modules + camel2DashComponentName: false, + }, + 'core', + ], + [ + 'babel-plugin-import', + { + libraryName: '@material-ui/icons', + libraryDirectory: 'esm', // or '' if your bundler does not support ES modules + camel2DashComponentName: false, + }, + 'icons', + ], + ], ``` -- [babel-plugin-transform-imports](https://www.npmjs.com/package/babel-plugin-transform-import) has a different api than `babel-plugin-import` but does same thing. +- [babel-plugin-transform-imports](https://www.npmjs.com/package/babel-plugin-transform-imports) with the following configuration: + ```js - [ - 'transform-imports', + plugins: [ + 'babel-plugin-transform-imports', { + '@material-ui/core': { + transform: '@material-ui/core/esm/${member}', + // for bundlers not supporting ES modules use: + // transform: '@material-ui/core/${member}', + preventFullImport: true, + }, '@material-ui/icons': { transform: '@material-ui/icons/esm/${member}', // for bundlers not supporting ES modules use: // transform: '@material-ui/icons/${member}', + preventFullImport: true, }, }, - ]; + ], ``` +#### 2. Convert all your imports + +Finally, you can convert your exisiting codebase to this option with our [top-level-imports](https://github.com/mui-org/material-ui/blob/master/packages/material-ui-codemod/README.md#top-level-imports) codemod. +It will perform the following diffs: + +```diff +-import Button from '@material-ui/core/Button'; +-import TextField from '@material-ui/core/TextField'; ++import { Button, TextField } from '@material-ui/core'; +``` + ## ECMAScript The package published on npm is **transpiled**, with [Babel](https://github.com/babel/babel), to take into account the [supported platforms](/getting-started/supported-platforms/). diff --git a/packages/material-ui-codemod/README.md b/packages/material-ui-codemod/README.md index e56808fbfb26d4..dda3ccf9e16074 100644 --- a/packages/material-ui-codemod/README.md +++ b/packages/material-ui-codemod/README.md @@ -60,6 +60,8 @@ Converts all `@material-ui/core` imports more than 1 level deep to the optimal f find src -name '*.js' -print | xargs jscodeshift -t node_modules/@material-ui/codemod/lib/v4.0.0/optimal-imports.js ``` +Head to https://material-ui.com/guides/minimizing-bundle-size/ to understand when it's useful. + #### `top-level-imports` Converts all `@material-ui/core` submodule imports to the root module: @@ -74,6 +76,8 @@ Converts all `@material-ui/core` submodule imports to the root module: find src -name '*.js' -print | xargs jscodeshift -t node_modules/@material-ui/codemod/lib/v4.0.0/top-level-imports.js ``` +Head to https://material-ui.com/guides/minimizing-bundle-size/ to understand when it's useful. + ### v1.0.0 #### `import-path`