ReviseAlgo Logo

Modules & Bundling

Tree Shaking

Master tree shaking optimization in JavaScript. Learn how build tools analyze ES Modules statically to strip out dead code and reduce bundle sizes.

Last Updated: July 15, 2026 10 min read

1. Introduction

Tree Shaking is a term used in the JavaScript ecosystem to describe dead-code elimination. It relies on the static structure of ES Modules (import and export statements) to analyze code and exclude unused modules from the final production bundle.

2. Why It Matters

Loading large utility libraries (like Lodash or Three.js) can significantly increase your bundle size. If you only use one or two functions from a large library, tree shaking allows your build tools to strip out the unused code, keeping bundle sizes small and improving load times.

3. Real-World Analogy

Think of a Fruit Tree in Autumn:

  • Legacy Bundling (Shipping the whole tree): To deliver apples to the store, you pack the entire tree—including the trunk, soil, branches, and dead leaves—into a massive container. The shipping cost is high.
  • Tree Shaking (Shaking the branches): You grab the trunk and shake the tree vigorously (static analysis). The dead leaves and branches fall off, leaving only the active fruit behind. You only pack and ship the fruit, saving shipping costs.

4. How Tree Shaking Works

Tree shaking is performed by bundlers (like Rollup, Webpack, or Vite) during the build process:
1. The bundler analyzes the import and export statements statically, building a dependency graph.
2. It traces which functions are actually called in your code.
3. Unused exports are marked as "dead code" and omitted from the compiled bundle.

During compilation, the bundler identifies that subtract() is never imported or called, and strips it out of the production bundle.

5. Common Blockers: Side Effects

A side effect is code that performs an operation outside its local scope (such as modifying global variables, adding event listeners, or writing to the console) when the file is loaded.
If a module has side effects, bundlers cannot safely remove it during tree shaking, even if none of its functions are called, because doing so could break application behavior:

6. Practical Example

This package configuration demonstrates flagging a module as side-effect free, allowing bundlers to safely shake it:

7. Common Mistakes

  • Trying to tree-shake CommonJS modules: Because CommonJS module exports are evaluated dynamically at runtime, bundlers cannot analyze exports statically, which makes tree shaking impossible. Always use ES Modules to support tree shaking.
  • Importing from monolithic files: Importing values from files that export large, complex objects (e.g. export default { a, b, c }) prevents tree shaking because the bundler must include the entire object in the bundle. Use named exports instead.

8. Quick Quiz

Q1: Why is tree shaking ineffective on CommonJS modules using require()?

A) CommonJS code runs in a sandbox

B) CommonJS dependencies are resolved dynamically at runtime, preventing static analysis

Answer: B — CommonJS modules are resolved dynamically at runtime, which prevents bundlers from analyzing exports statically during compilation.

9. Scenario-Based Challenge

The Monolithic Object Refactor:

A utility file exports a large config container: export default { methodA, methodB, methodC }. This prevents bundlers from tree-shaking the module. Refactor the file to use named exports instead, allowing bundlers to strip out unused functions.

10. Debugging Exercise

Explain why importing this math library compiles the entire module instead of tree-shaking it:

// math.js
export default {
  add(a,b) { return a+b; },
  multiply(a,b) { return a*b; }
};
// app.js
import MathMethods from './math.js';
console.log(MathMethods.add(1, 2)); // multiply is still included in bundle! Why?
View Solution

Diagnosis: The file exports a single default object containing all functions. Because the object properties are evaluated at runtime, bundlers cannot safely split or remove properties from the exported object, preventing tree shaking.

Fix: Refactor the module to use named exports, allowing bundlers to analyze and shake unused exports statically:

// math.js
export function add(a, b) { return a + b; }
export function multiply(a, b) { return a * b; }
// app.js
import { add } from './math.js'; // multiply is successfully stripped out!

11. Interview Questions

🟢 Q1: What is tree shaking and what conditions are required for it to work?

Answer: Tree shaking is a build optimization that removes unused code from the production bundle.
For tree shaking to work, the following conditions must be met:
1. ES Module Syntax: Code must use static ES Modules (import and export), allowing static analysis.
2. Named Exports: Avoid exporting monolithic default objects, using named exports instead.
3. Side-Effect Free: Modules should be side-effect free, or side effects must be declared in package.json using the sideEffects property.
4. Compatible Build Tools: The build tools must be configured to optimize code during compilation.

12. Production Considerations

  • Configure sideEffects: Flag side-effect free files in your project's package.json file using "sideEffects": false. This allows bundlers to safely strip out unused files during compilation, reducing bundle size.