Material UI Icons are not being tree shook
See original GitHub issue- I have searched the issues of this repository and believe that this is not a duplicate.
Expected Behavior
I use WebPack and have Tree Shaking setup, I only use a few icons from material-ui-icons
, with imports like like import {Edit, AddBox} from 'material-ui-icons';
and expect the tree shaking algorithm to strip out all the unused icons from the bundle.
Current Behavior
Analyzing the contents of my production bundle I see that the entirety of material-ui-icons is used in my bundle, including piles of icons I definitely do not use.
And I manually verified that icons I do not use are present in the bundle.
Looking at the contents of node_modules/material-ui-icons/, I notice that while an index.es.js exists and is being used, the modules being imported themselves appear to be CommonJS modules.
Given the “Use ES2015 module syntax (i.e. import and export).” limitation of tree shaking, I have a feeling that the reason .
It’s a side topic but I just realized that the analysis of the Material-UI import looks strange as well. Material UI has an entire material-ui/es/
folder and an index.es.js
that is being imported, but it looks as if all the modules are being imported from the CommonJS modules instead of the modules inside material-ui/es/
.
Your Environment
Tech | Version |
---|---|
Material-UI | 1.0.0-beta.38 |
Material-UI-Icons | 1.0.0-beta.36 |
React | 16.2.0 |
WebPack | 3.11.0 |
Babel | 6.26.0 |
Issue Analytics
- State:
- Created 5 years ago
- Reactions:6
- Comments:7 (6 by maintainers)
Top GitHub Comments
I want to confirm that tree shaking works…in production only!
TL;DR
Background
development
bundle, we noticed a gz size of 14mb and a stat size of 80mb, of which the @material-ui/icons packages was 32mb.Cause
development
modeHere is the result of aliasing multi repo dependencies to just the local app node_modules, you can see the sheer size of @material-ui/icons accounting for ~30% of the stat size:
Solution
This applies to dev only, and I repeat - it has no bearing on a production build. Production builds with tree shaking work just fine when importing from an esm index.
If you want to optimize dev builds:
e.g. replace
import { Home } from '@material-ui/icons'
withimport Home from '@material-ui/icons/Home'
I hope my few hours of hair pulling helps someone out!
Once again, this has no bearing on production, and only applies to optimizing a dev build.
For posterity I just ran the following tests on my project, by changing the
sideEffects
in thepackage.json
of@material-ui/core
and@material-ui/icons
directly innode_modules
. Bundle sizes uncompressed:Tests on
core
:import { ... } from '@material-ui/core'
with"sideEffects": true
incore
: 956kbimport { ... } from '@material-ui/core'
with"sideEffects": false
incore
: 790kbimport Foo from '@material-ui/core/Foo'
with"sideEffects": true
incore
: 789kbimport Foo from '@material-ui/core/Foo'
with"sideEffects": false
incore
: 789kbTests on
icons
:import { Bar } from '@material-ui/icons'
with"sideEffects": true
inicons
: 3.87mbimport { Bar } from '@material-ui/icons'
with"sideEffects": false
inicons
: 793kbimport Bar from '@material-ui/icons/Bar'
with"sideEffects": true
inicons
: 789kbimport Bar from '@material-ui/icons/Bar'
with"sideEffects": false
inicons
: 789kbAt first I thought tree-shaking was not working because bundle size are slightly different when using the different import styles, but that difference is negligible (789 -> 790 for
core
and 789 -> 793 foricons
), but this is likely due to the code added by Webpack to tree shake. The difference is massive when turning off tree-shaking so it definitely works.