Explain tree-shaking (dead code elimination) in modern bundlers, the requirements for it to work (ESM, sideEffects, pure), and how to verify results. Include common pitfalls that prevent tree-shaking.
Tree-Shaking: How It Works and Common Pitfalls
Use guided tracks for structured prep, then practice company-specific question sets when you want targeted interview coverage.
What is tree-shaking?
Tree-shaking is dead code elimination. Bundlers analyze your import graph and remove unused exports so your final bundle is smaller and faster. It works best with ESM because imports/exports are static.
Requirement | Why it matters | Example |
|---|---|---|
ESM exports | Static analysis of imports | export const foo = ... |
No side effects | Unused code can be safely removed | set "sideEffects": false |
Pure annotations | Signals safe removal | /* @__PURE__ */ helper() |
// Good: named ESM exports
export const add = (a, b) => a + b;
export const multiply = (a, b) => a * b;
// Consumer uses only add
import { add } from './math.js';
Pitfall | Why it breaks tree-shaking | Fix |
|---|---|---|
CommonJS modules | Require is dynamic | Publish ESM build |
Side-effect imports | Bundler must keep them | Mark sideEffects accurately |
Barrel files with side effects | Re-export triggers file execution | Keep barrels side-effect free |
Dynamic require/import | Unknown at build time | Prefer static imports |
How to verify
Use a bundle analyzer to compare sizes before/after. In devtools, inspect the output bundle to ensure unused exports are removed. Add perf budgets to prevent regressions.
Tree-shaking is effective when your code is ESM, side-effect free, and statically analyzable. If bundles stay large, check for CJS dependencies and unmarked side effects.