Vite is the new kid in town and I predict will eventually replace Webpack. Ah yes, the death of webpack has been foretold around many dev huddles. But I really do believe Vite will succeed as it is far faster and modern. For example, Vite embraces ES Modules as a core feature, whereas Webpack still considers ES module output as experimental as of July 2022.
Given Vite uses ES modules, is tree shaking free? Essentially yes in most cases. But one still needs to be careful with npm packages as many of them are still CommonJS.
But first we need to understand the problem and why we even need tree shaking.
lodash is one of the most popular npm packages. It is a library that offers many small utilities. The typical usage of it looks something like this.
Even though we used a single
_.map function, when we build our app with Vite the entirety of
lodash will be included. This is because the top level export of
lodash is a single CommonJS export. Tree shaking only works with ES modules.
Doing a quick test, the bundle size comes out to be about 87 KiB.
lodash team knows about this problem and does offer a solution with single function exports.
This is annoying to manage but does bring the bundle size down to 18 KiB.
But we can do better! We can use proper ES modules.
lodash-es is an ES module build that is offered by the lodash team. They publish both CommonJS and ES module builds. So tree shaking should just work right? Unfortunately there are gotchas.
lodash-es still exports everything as a single object as the default ES module export, which means nothing is tree shakable. The bundle size remains at 87 KiB.
The fix is to use a different import syntax.
The bundle size goes down to 17 KiB.
_.chain? Can we tree shake that?
Unfortunately if one uses
_.chain with Vite in dev mode, everything seems to work. But that is a trap as everything will be tree shaken off when a build is made.
But there is a workaround! Build your own chain.
Oh boy that is complicated and is annoying having to manually add which methods one wants, but it keeps the bundle size small at 17 KiB.