
Tree Shaking
Tree shaking is the bundler’s process of removing unused exports from the final bundle. It relies on static analysis of ES module import/export syntax.
How It Works
ES modules (import/export) are statically analyzable — the bundler knows at build time which exports are used. CommonJS (require/module.exports) is dynamic and cannot be statically analyzed.
// utils.js — ES module
export function add(a, b) { return a + b; }
export function multiply(a, b) { return a * b; }
// app.js
import { add } from './utils'; // only 'add' is used The bundler traces: add is imported, multiply is not → multiply is dead code → remove it from the output.
Requirements for Tree Shaking
- ES module syntax —
import/export, notrequire/module.exports - Bundler with tree-shaking — Rollup, Vite, or Webpack in production mode
- Side-effect-free modules — modules that modify global state on import won’t be removed
package.json sideEffects
Libraries must declare which files have side effects:
{
"name": "my-ui-lib",
"sideEffects": false
} Or list specific files with side effects:
{
"sideEffects": ["./src/polyfills.js", "*.css"]
} Without this field, bundlers assume every module may have side effects and won’t remove unused ones.
Barrel Files Kill Tree Shaking
Re-export files (index.js that re-exports everything) can defeat tree shaking:
// components/index.js
export { Button } from './Button';
export { Modal } from './Modal';
export { HeavyTable } from './HeavyTable'; // large component
// App.js
import { Button } from './components';
// may import ALL components in bundlers without full scope hoisting Fix: import directly from the source file.
import { Button } from './components/Button'; Vite and Rollup handle barrel files better than Webpack due to more aggressive scope hoisting.
Checking Your Bundle
npx vite-bundle-visualizer Large unexpected chunks suggest tree shaking isn’t working — check for CommonJS imports or missing sideEffects declarations.









