Tree Shaking

Sep 22, 2022

Code bundles rapidly grow in size as projects depend on more third-party code. For browser clients, that can mean a slower time to first paint. For mobile clients, longer download times. For edge runtimes, code bundles need to be as small as possible.

But a significant portion of code that ships in the bundle won't ever be used. Maybe only a single isolated function is imported out of a lengthy package. So how do we get rid of the bad code?

The idea is tree-shaking – analyzing a program's control flow to see what functions will be called and removing unused code.

For statically compiled languages, the compiler does the heavy work. GCC and LLVM do dead code elimination. But, of course, code can only (safely) be removed if it is unused unconditionally – i.e., it will never be called even under different runtime environments.

Dynamic languages like JavaScript have a much harder problem. ECMAScript 6 modules can be tree-shaken more efficiently since they are statically loaded (vs. CommonJS's dynamic loading). Instead of compilers, bundlers perform most of the tree-shaking in the JavaScript world.

You can mark functions with a @__PURE__ comment directive that hints to the bundler that a function can be removed without side effects if it isn't used.

Tree shaking algorithms will increasingly be more important as two things continue to be true (1) more code dependencies and (2) code deployed on edge runtimes.