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.
The 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
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
Unfortunately, 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.
lodash-es
The bundle size goes down to 17 KiB.
import * as _
(demo) is creating a module object and means "gather all the exports into an object with the identifier _
".
This makes lodash-es
tree shakable because Vite can trace the usage of the module object. The module object isn't extensible, I.E. new properties cannot be added to it. Therefore, it is possible for Vite to comprehensively track which functions were being used and tree shake everything else. This isn't possible with the default export nor CommonJS default export as those are plain old JavaScript object.
_.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.
Do you want to keep those JavaScript bundles small? You're in luck, Battlefy is hiring.