Frontend Development 20 min read

How Rollup’s Tree‑Shaking Eliminates Dead Code: A Deep Dive

This article explains the fundamentals and implementation details of Rollup's tree‑shaking feature, showing how unused JavaScript code is identified and removed through static ES6 module analysis, with practical code examples and visual demonstrations of variable, function, and class elimination.

WeDoctor Frontend Technology
WeDoctor Frontend Technology
WeDoctor Frontend Technology
How Rollup’s Tree‑Shaking Eliminates Dead Code: A Deep Dive

Tip: This article uses Rollup version v2.47.0.

1. Understanding Tree‑shaking

1.1 What is Tree‑shaking?

Tree‑shaking, first popularized by Rollup, essentially removes unused JavaScript code by including only the parts of a module that are actually imported.

Webpack adopted a similar feature later, but the core idea remains: treat the entry file as the tree trunk and its dependencies as branches, and discard code that is never used.

Tree‑shaking works only with ES6 module syntax because static analysis can determine which imports are used, while CommonJS modules require plugins to be transformed first.

1.2 Why is Tree‑shaking needed?

Large web applications contain a lot of JavaScript, and browsers spend significant resources processing it. Removing dead code reduces bundle size, shortens load time, and improves user experience.

2. Deep Dive into Tree‑shaking

2.1 Dead Code Elimination (DCE)

Dead code elimination (DCE) is the process of discarding code that does not affect the program output. Rollup implements DCE as a form of tree‑shaking, focusing on unused imports rather than unreachable code.

Code that is never executed or reachable

Code whose result is never used

Code that only writes to dead variables (write‑only)

2.2 ES6 Module Characteristics

Only top‑level statements can be modules

Import specifiers must be string literals

Import bindings are immutable

With these guarantees, Rollup can safely eliminate unused imports.

2.3 Practical Demonstration

The following examples show how Rollup removes unused variables, functions, and classes during bundling.

2.3.1 Variable Elimination

The bundled output does not contain variables

b

and

c

because they are never used.

2.3.2 Function Elimination

Functions

util1()

and

util2()

are omitted from the bundle since they are imported but never called.

2.3.3 Class Elimination

Only referenced but not instantiated

When a class file is imported but none of its methods or properties are used, Rollup can drop the class entirely.

2.3.4 Side Effects

Rollup cannot eliminate side effects in certain cases, such as when a module’s class methods are imported but not used, or when a module modifies global variables.

Examples of side‑effect limitations are shown below:

3. Tree‑shaking Implementation Process

Rollup parses source files into an AST using Acorn, then traverses the tree to mark which nodes are included based on usage.

<code>const ast = this.acornParser.parse(code, { ...(this.options.acorn), ...options });</code>

During the

rollup()

phase, modules are created and their static and dynamic dependencies are resolved.

<code>private async fetchModule({ id, meta, moduleSideEffects, syntheticNamedExports }, importer, isEntry) { ... }</code>

Each module’s AST is analyzed, and inclusion marks are set. The

include()

method triggers tree‑shaking by checking whether a node should be kept.

<code>include(): void { const context = createInclusionContext(); if (this.ast!.shouldBeIncluded(context)) this.ast!.include(context, false); }</code>

The

treeshakeNode()

function physically removes dead code from the generated bundle.

<code>export function treeshakeNode(node, code, start, end) { code.remove(start, end); /* remove annotations if any */ }</code>

Finally, the

generate()

or

write()

phase writes the optimized bundle to disk.

<code>async function handleGenerateWrite(...) { const bundle = new Bundle(...); const generated = await bundle.generate(isWrite); /* write files */ }</code>

Conclusion

Rollup’s tree‑shaking works by starting from the entry file, tracing all imported variables, and discarding any code that is not referenced, resulting in a minimal bundle without extra configuration as long as the code follows ES6 module syntax.

JavaScriptcode optimizationTree ShakingRollupES6 modulesbundling
WeDoctor Frontend Technology
Written by

WeDoctor Frontend Technology

Official WeDoctor Group frontend public account, sharing original tech articles, events, job postings, and occasional daily updates from our tech team.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.