2.3 KB | 18% | 45 ms | 0.68 s |
| Optimized (Tree Shaking + DCE + sideEffects: false) | 4.7 KB | 2% | 28 ms | 0.41 s |
Key Findings:
- Tree shaking alone reduces bundle size by ~84% compared to baseline imports.
- Combining Tree Shaking with DCE and explicit
sideEffects configuration yields a 94% reduction in unused code.
- Parse time and TTI scale non-linearly with bundle size; dropping below 10KB gzipped significantly improves perceived performance on 3G/4G networks.
Core Solution
Optimizing bundle size requires understanding the distinct mechanisms of Dead Code Elimination (DCE) and Tree Shaking, and configuring your build pipeline to leverage both.
Dead Code Elimination (DCE): The Surgeon
DCE operates at the code/function level. It analyzes control flow and removes unreachable branches, unused variables, and functions that are never invoked.
js if (false) { console.log("This will never run"); }
DCE removes it completely
js function unusedFunction() { return 42; }
If never called → removed
DCE targets unreachable code, unused variables, and dead branches. It requires a production build configuration (e.g., mode: 'production' in Webpack) to activate advanced minification passes like Terser or SWC.
Tree Shaking: The Gardener
Tree Shaking operates at the module/import level. It relies on static ES6 import/export syntax to build a dependency graph and prune unused exports.
js import { debounce, throttle } from "lodash-es";
If you only use:
js debounce()
throttle gets removed
Tree Shaking only includes what is explicitly consumed. It cannot function with dynamic module systems.
Why ES Modules Matter
Tree Shaking depends on:
ES6 modules (import/export)
Because they are:
Static (analyzable at build time)
js const lib = require("lodash");
Dynamic → bundler can’t analyze usage
js import { debounce } from "lodash-es";
Bundler knows exactly what’s used
How to Make Your Code Shakeable
Using a bundler isn’t enough. You need to write shake-friendly code.
1. Avoid Side Effects
js import "./init"; // modifies global state
Bundler won’t remove it
Mark in package.json:
json { "sideEffects": false }
2. Use Named Exports
js export default { a, b, c };
js export const a = ... export const b = ...
Bundler can pick only what’s needed
3. Import Only What You Need
js import _ from "lodash";
js import { debounce } from "lodash-es";
Smaller bundle instantly
Pitfall Guide
- Relying on Default Exports: Default exports bundle all module members into a single object, preventing static analysis from isolating unused exports. Always prefer named exports for library code.
- Ignoring Side Effects: Unmarked side effects (global mutations, polyfills, CSS imports) force bundlers to conservatively retain entire modules. Explicitly declare
sideEffects in package.json to enable safe pruning.
- Using CommonJS in Modern Bundlers:
require() resolves at runtime, making dependency graphs unpredictable. Tree shaking requires static import/export syntax to function.
- Assuming All Libraries Are Tree-Shakeable: Many npm packages still ship CJS builds or pre-bundled UMD files. Always verify if a package provides an ESM entry point (e.g.,
lodash-es, date-fns).
- Over-Importing from Utility Libraries: Importing the entire namespace (
import _ from "lodash") defeats static analysis. Use deep imports or ESM-compatible variants to isolate specific functions.
- Skipping Production Mode Configuration: Tree shaking and DCE are often disabled in development builds. Ensure your bundler is configured for production (
mode: 'production', optimization.usedExports: true) to activate these optimizations.
Deliverables
📘 Shake-Ready Architecture Blueprint
A step-by-step guide to auditing your dependency graph, configuring bundlers for static analysis, and validating unused code elimination. Includes module resolution strategies, ESM migration patterns, and production build optimization workflows.
✅ Pre-Deployment Bundle Optimization Checklist
⚙️ Configuration Templates
package.json sideEffects declaration template
- Webpack 5 production config (
optimization.sideEffects, module.rules for ESM)
- Rollup
treeshake configuration with moduleSideEffects and pureExternalModules settings
- Vite/Rollup tree-shaking validation script for CI/CD pipelines