DEV Community

Cover image for The Diet Your App Deserves: Tree Shaking vs Dead Code Elimination
Abdullah al Mubin
Abdullah al Mubin

Posted on

The Diet Your App Deserves: Tree Shaking vs Dead Code Elimination

We’ve all done this:

  • Install a huge library
  • Use ONE function
  • Ship 300KB of JavaScript

In modern web apps:

Shipping less code = faster apps


Two terms always come up here:

  • Tree Shaking
  • Dead Code Elimination (DCE)

They sound similar…

But they work in very different ways.

Let’s break it down with a real-world example so it actually sticks.


Table of Contents


The Problem: Bloated Bundles

Imagine your app loads slowly.

Users wait…

Bounce rate increases


You check your bundle:

500KB JavaScript

But your actual logic?

Maybe 50KB


So what happened?

Unused code is being shipped


Real-World Scenario: The Overloaded App

You’re building:

quickdash.com (a dashboard app)


You install a utility library:

import _ from "lodash";
Enter fullscreen mode Exit fullscreen mode


`

But you only use:

js
_.debounce()


What gets shipped?

The ENTIRE library


Result

  • Bigger bundle
  • Slower load time
  • Worse performance

This is where optimization kicks in.


Dead Code Elimination (DCE): The Surgeon

DCE is the classic optimization technique.

What it does

Removes code that will never run


Example

js
if (false) {
console.log("This will never run");
}

DCE removes it completely


Another Example

js
function unusedFunction() {
return 42;
}

If never called → removed


Analogy

A surgeon removing useless organs

Precise. Logical. Necessary.


What DCE Targets

  • Unreachable code
  • Unused variables
  • Functions never called

It works at code level


Tree Shaking: The Gardener

Tree Shaking works differently.

What it does

Removes unused imports/modules

Example

js
import { debounce, throttle } from "lodash-es";

If you only use:

js
debounce()

throttle gets removed


Analogy

Shaking a tree so dead leaves fall off

Only what’s needed stays.

Key Idea

Include ONLY what you use

Works at module level


Why ES Modules Matter

Tree Shaking depends on:

ES6 modules (import/export)


Why?

Because they are:

Static (analyzable at build time)


CommonJS (bad for tree shaking)

js
const lib = require("lodash");

Dynamic → bundler can’t analyze usage


ES Modules (good)

js
import { debounce } from "lodash-es";

Bundler knows exactly what’s used


Key Differences

Feature Dead Code Elimination Tree Shaking
Level Code / function Module / import
Removes Unreachable code Unused exports
Works with Any JS ES Modules only
Timing After code analysis During bundling

How to Make Your Code Shakeable

Using a bundler isn’t enough.

You need to write shake-friendly code


1. Avoid Side Effects

Bad:

js
import "./init"; // modifies global state

Bundler won’t remove it


Good

Mark in package.json:

json
{
"sideEffects": false
}


2. Use Named Exports

Bad:

js
export default {
a,
b,
c
};


Good:

js
export const a = ...
export const b = ...

Bundler can pick only what’s needed


3. Import Only What You Need

Bad:

js
import _ from "lodash";


Good:

js
import { debounce } from "lodash-es";


Smaller bundle instantly


Real Impact

Without optimization:

  • Large JS bundles
  • Slow page load
  • Poor mobile performance

With Tree Shaking + DCE:

  • Smaller bundles
  • Faster load times
  • Better user experience

Mental Model

If you remember just this:

  • DCE → Removes code that can’t run
  • Tree Shaking → Removes code you didn’t import

DCE cleans inside your code
Tree Shaking trims your dependencies


Final Thoughts

Tree Shaking and DCE are invisible…

But powerful.

They:

  • Reduce bundle size
  • Improve performance
  • Make apps faster

The fastest code is the code you never ship.


What About You?

Do you:

  • Check your bundle size?
  • Use tools like Webpack Analyzer?
  • Optimize imports?

Let’s discuss in comment...

Top comments (0)