rafaelalmeidatk / TIL

I learn something new almost everyday. Here I post stuff to my future self and to other people that may need it
4 stars 0 forks source link

Fixing tree-shaking with static properties/namespace components #7

Open rafaelalmeidatk opened 4 years ago

rafaelalmeidatk commented 4 years ago

It is very common to see the namespace components pattern being utilized, it makes it easier to compose components that belong together, without having to import every single component into the scope (Menu, MenuApples, MenuOranges, etc.):

<Menu>
  <Menu.Apples />
  <Menu.Oranges />
</Menu>

To make this work you may have something like this on the component code:

import Apples from './Apples';
import Oranges from './Oranges';

const Menu = () => <div />;
Menu.Apples = Apples;
Menu.Oranges = Oranges;

export default Menu;

There is a problem with this code though: it doesn't work with tree-shaking.

By adding static properties to the Menu component, the bundler considers that you are creating side-effects, and these can't be removed from the final bundle since it is hard to analyze if the code is really utilized or not.

Fortunately, there is a way to flag to the bundler that the code is pure and can be safely stripped from the final bundle, by using the /*#__PURE__*/ annotation in a statement. Combining it with Object.assign we can easily fix the tree-shaking problem:

import Apples from './Apples';
import Oranges from './Oranges';

const Menu = () => <div />;

const FinalMenu = /*#__PURE__*/ Object.assign(Menu, { Apples, Oranges });

export default FinalMenu;

Now the component won't be included if it isn't imported in the project! This can also be utilized to fix the same problem when using multiple static properties like displayName, defaultProps or any other property name. Looks like that if it has more than one property being introduced with an assignment (foo.bar = 'bar';), it will be considered as a side-effect and the tree-shaking will not work.