Skip to content

Tree Shaking & Code Splitting

Tree shaking is dead code elimination — removing unused exports from JavaScript bundles. It relies on ES module’s static structure.

// 📁 utils.js
export function used() { return 'used'; }
export function unused() { return 'never used'; }
// 📁 main.js
import { used } from './utils.js';
// 'unused' is removed during tree shaking 🎯
// ✅ ES modules (static analyzable)
export const value = 42;
// ❌ CommonJS (cannot be tree-shaken)
module.exports = { value: 42 };
// ✅ Import only what you need
import { map, filter } from 'lodash-es';
// ❌ Importing the whole library
import _ from 'lodash';
// ✅ Side-effect free modules
// package.json: "sideEffects": false

Code splitting breaks your bundle into smaller chunks that can be loaded on demand, reducing the initial load size.

// webpack/vite: multiple entry points
module.exports = {
entry: {
main: './src/main.js',
admin: './src/admin.js'
}
};
// Route-based splitting (most common)
const Home = () => import('./routes/Home.js');
const About = () => import('./routes/About.js');
const Dashboard = () => import('./routes/Dashboard.js');
// Route: load on navigation
async function navigate(route) {
switch (route) {
case 'home': return (await Home()).default;
case 'about': return (await About()).default;
case 'dashboard': return (await Dashboard()).default;
}
}
// webpack: split vendor code
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
}
}
}
}
// Check bundle sizes
console.log(`Initial bundle: ${bundleSize / 1024}KB`);
console.log(`Lazy loaded chunk: ${chunkSize / 1024}KB`);
// After optimization
// 200KB → 50KB initial + 50KB lazy = 75% reduction 🚀
TechniqueWhat It DoesBenefit
Tree ShakingRemoves unused codeSmaller bundles
Code SplittingSplits into chunksFaster initial load
Dynamic ImportLoads on demandLazy loading
Vendor SplittingSeparates library codeBetter caching