In modern frontend development, tree shaking is essential for keeping bundles lean. Yet many developers unknowingly break it with subtle mistakes in import and export usage.
Tree shaking is one of the most effective ways to reduce your JavaScript bundle size — but only if your code is written in a way that allows it.
Unfortunately, a few common export and import patterns can silently prevent tree shaking from working at all.
This guide covers the best practices to keep your code tree-shakable in modern frontend stacks (React, Vite, Webpack, etc.).
Use Named Exports Instead of default
Named exports make it easier for bundlers to remove unused code.
// ❌ Not tree-shakable
export default {
add,
subtract,
};
// ✅ Tree-shakable
export const add = () => {};
export const subtract = () => {};
Tree shakers like Rollup and Webpack can’t shake off unused properties of a default-exported object.
Avoid Exporting Object Literals
Exporting a single object with all your functions may feel clean, but it bundles everything, even unused parts.
// ❌ Everything in utils is included
export const utils = {
toDate,
formatPrice,
};
// ✅ Only what’s used is bundled
export const toDate = () => {};
export const formatPrice = () => {};
Don’t Export Destructured Variables
const config = {
API_URL: '...',
TIMEOUT: 3000,
};
// ❌ Not tree-shakable
export const { API_URL, TIMEOUT } = config;
// ✅ Better
export const API_URL = '...';
export const TIMEOUT = 3000;
Destructuring hides the actual bindings from the bundler.
Use Direct Re-exports
// utils/index.js
// ✅ Good
export * from './math';
export * from './date';
// ✅ Even better (explicit)
export { add, subtract } from './math';
Avoid logic-based re-exports or dynamic code.
Avoid Wildcard Imports
// ❌ Not tree-shakable
import * as utils from './utils';
// ✅ Tree-shakable
import { formatDate } from './utils';
Wildcard imports bring in everything — even what you don’t use.
Mark sideEffects: false in package.json
This lets the bundler safely remove unused files/modules.
{
"sideEffects": false
}
If some files (like CSS) do have side effects, specify them:
{
"sideEffects": ["./styles/global.css"]
}
Avoid Dynamic Aggregation
// ❌ Cannot be tree-shaken
const all = {
...require('./module1'),
...require('./module2'),
};
export default all;
Tree shaking only works with static imports/exports that bundlers can analyze at build time.
Final Thoughts
Writing tree-shakable code is about making your modules predictable and explicit. It's not just about saving bytes — it's about better performance, better dev experience, and cleaner architecture.
Your imports and exports are the first line of defense against bloat.
If you're optimizing a large codebase and want to refactor for better tree shaking, start by:
- Replacing default object exports
- Flattening utility files
- Removing wildcard imports
- Splitting large shared files into named modules
💬 Have more tips? Share them in the comments.
Follow me for more performance tips and frontend architecture insights.
#JavaScript
#Frontend
#TreeShaking
#ESModules
#React
#Vite
#Webpack
#TypeScript
#CleanCode
#WebPerformance
Top comments (0)