How to make your library tree-shakable
Tags: javascript, typescript, webdev, react
Published: 2022-11-25 20:39:06

##Tree shaking
Tree shaking is a term commonly used in the JavaScript context for dead-code elimination. Although many bundlers nowadays support tree-shaking like Rollup or Webpack, tree-shaking is not just an on/off feature. To make tree-shaking becomes valuable, there are many factors that affect the quality

Basically, Tree shaking is detecting which exports are unused in our application when bundling and won’t include it into our bundler.

##Achieve Tree-shaking
From tree-shaking basic definition, many bundlers support it by default, you might don’t have to do any thing. Look at my example below:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/czafqbq0ipj3ajbjg5zh.png)

Here is my library called `common-ui` , I split my code into small modules and export them all in the root `index.ts` file. And here is my bundler config ( tsup ) and the dist folder after I built it


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kfunw52j3pprq2kn8rvo.png)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6sn0yis1wwm1h247y1tw.png)

This is the most basic config though. I only set up the entry point to the index.ts . So every line of code that are not exported and used by this file won’t be included in our dist folder. By this way, you are achieving dead code elimination right ?


##But it is more complicated than that
A library is nothing without an application that uses it, since my example is a monorepo. I will create a package to use the library


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tp2rue7m768mo5voq7u1.png)

The `web` package will install the `common-ui` package and uses its components:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/036yh3kdmjwte207lr9q.png)

You can see that I imported 9 components from the `common-ui` library, let’s see what is the bundle size of my web application


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bhp0jku7xwe7wdfy2iiz.png)


It’s 258kb, quite heavy. So let’s see if I remove few imports from the `common-ui` library to reduce the bundle size

Well…. I tried to remove half of the imports, but the bundle size still the same. So the tree-shaking thing I did above absolutely didn’t help.

##Why ?
This is because **Common JS Modules** VS **ES6 Modules**

The significant difference is that **ESM imports are static whereas CJS imports are dynamic**

`TSup` uses `esbuild` as its bundler and it supports both formats

Tree shaking relies on static code analysis. It detects which modules are necessary for the code to work and eliminates other modules from the final bundle during compile time.

#So ESM is a requirement for Tree-Shaking feature.

Let’s change our config file a bit


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f9es5k20os4fdlxt9y2a.png)

By setting the formats for both CommonJS modules and ES6 modules and multiple entry points, our bundle will look like this


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/llychlwp4cxamdkuxq89.png)


For every module in our files, there will be both `.cjs` file and `.js` file for CommonJS and ES6 modules respectively. In our `package.json` file:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7rjwc2gr4ygmm24mqaw8.png)

We map the `.cjs` and `.js` and `.d.ts` files and set the side effects optimization and make our library side effects free. Now let’s get back to our web application to see if the bundle size is smaller when I remove imports


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a4h8ok724r4fjx5l5nn5.png)

You can see I removed the `CodeEditor` component, and run the build


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/96eiclqhmwt8cntvdrgr.png)

The bundled size is smaller from the 260kb above because the bundler detected we only use parts of the library so It won’t include whole library into to bundled file.

##Conclusion
Tree shaking a library is not simple. Its quality depends on multiple factors and this article presents the basics. Understand what is the bundled output and the formats are the basics to make our library tree-shakable


You can check out [my source code here](https://github.com/leduc1901/monorepo-nx-treeshaking)

##Last words
Although my content on dev.to is free for everyone, but if you find this article helpful, [you can buy me a coffee here](https://www.buymeacoffee.com/kylele19)