Home Work Blog About Contact
Back to blog

Tree Shaking in React.js: Keep Your Bundles Light and Fast

Tree Shaking in React.js: Keep Your Bundles Light and Fast

What is Tree Shaking?

Think of your favorite streaming service. It has thousands of movies and TV shows, but when you download content for offline viewing, you only download the specific episodes you want to watch. You don't download the entire Netflix library to your phone!

Tree shaking works the same way with your React code. It looks at all the code available in the libraries you've installed and only "downloads" the parts your app actually uses into the final bundle that users receive.

graph TD
    A[Full Library<br/>📚 1000+ functions] --> B{Tree Shaking<br/>🌳}
    B --> C[Your Bundle<br/>📦 Only 3 functions used]

    style A fill:#ffebee
    style B fill:#e8f5e8
    style C fill:#e3f2fd

Why Should You Care?

When you install a library like Lodash (which has hundreds of utility functions), you might only use 2-3 functions. Without tree shaking, your users would download the entire library, making your app slower to load.

The impact:

  • Smaller bundle sizes

  • Faster loading times

  • Better user experience

  • Lower bandwidth usage

How Tree Shaking Works in React

Tree shaking relies on ES6 module syntax. Modern bundlers like Webpack (which Create React App uses) can analyze your imports and only include what you actually use.

flowchart LR
    A[Source Code<br/>with ES6 imports] --> B[Webpack/Bundler<br/>🔍 Analysis]
    B --> C{Static Analysis}
    C --> D[Dead Code<br/>❌ Removed]
    C --> E[Used Code<br/>✅ Included]
    E --> F[Final Bundle<br/>📦 Optimized]

    style A fill:#f3e5f5
    style B fill:#e8f5e8
    style D fill:#ffebee
    style E fill:#e8f5e8
    style F fill:#e3f2fd

The Magic of ES6 Imports

// ✅ Tree-shakable - only imports what you need
import { debounce, throttle } from 'lodash-es';

// ❌ Not tree-shakable - imports everything
import _ from 'lodash';
const debouncedFn = _.debounce(myFunction, 300);

Simple Best Practices

1. Use Named Imports

Always import specific functions instead of entire libraries:

// ✅ Good
import { useState, useEffect } from 'react';
import { format } from 'date-fns';

// ❌ Bad
import * as React from 'react';
import * as dateFns from 'date-fns';

2. Choose Tree-Shake Friendly Libraries

Some libraries are better than others:

Good choices:

  • lodash-es (instead of lodash)

  • date-fns (instead of moment)

  • Modern MUI (v5+) with top-level imports

  • Libraries built with ES6 modules

Example with Material-UI (MUI v5+):

// ✅ Modern MUI - supports tree shaking with top-level imports
import { Button, TextField } from '@mui/material';

// ❌ Outdated pattern - no longer necessary and slower in development
import Button from '@mui/material/Button';
import TextField from '@mui/material/TextField';

Note: Since MUI v5, modern bundlers automatically tree-shake unused components from top-level imports, making the old individual import pattern unnecessary.

graph TD
    A1["Bad Import: import * from library"] --> B1["Entire Library<br/>500KB"]
    A2["Good Import: import func1, func2"] --> B2["Only Used Functions<br/>50KB"]

    B1 --> C1["Large Bundle<br/>Slow Loading"]
    B2 --> C2["Small Bundle<br/>Fast Loading"]

    style B1 fill:#ffebee
    style B2 fill:#e8f5e8
    style C1 fill:#ffebee
    style C2 fill:#e8f5e8

3. Import from Specific Paths

When possible, import directly from the function's file:

// ✅ Even better tree shaking
import debounce from 'lodash-es/debounce';

// ✅ Still good
import { debounce } from 'lodash-es';

Real React Examples

Component Organization

// components/index.js - Be specific with exports
export { Button } from './Button';
export { Modal } from './Modal';

// In your React component
import { Button, Modal } from './components';

Utility Functions

// utils/helpers.js
export const formatDate = (date) => { /* ... */ };
export const debounceSearch = (fn) => { /* ... */ };

// In your component - only import what you need
import { formatDate } from './utils/helpers';

Quick Wins for Your React App

Check Your Bundle Size

If you're using Create React App, run:

npm run build

Look at the generated build folder to see your actual bundle sizes.

Use Bundle Analyzer

Install and run webpack-bundle-analyzer to visualize what's in your bundle:

npm install --save-dev webpack-bundle-analyzer
npm run build
npx webpack-bundle-analyzer build/static/js/*.js

Common Libraries to Watch

Heavy libraries that benefit from tree shaking:

  • Lodash (use lodash-es instead)

  • MUI components (v5+ supports top-level imports)

  • Icon libraries (like react-icons)

  • Utility libraries

  • Date manipulation libraries

Common Mistakes to Avoid

1. Importing CSS with Components

// This can prevent tree shaking
import 'some-library/dist/styles.css';
import { Component } from 'some-library';

2. Using Barrel Exports Incorrectly

// index.js - avoid this pattern
export * from './component1';
export * from './component2';

// Better approach
export { Component1 } from './component1';
export { Component2 } from './component2';

When Tree Shaking Happens

Tree shaking optimization primarily occurs during production builds with tools like Webpack, Rollup, or Vite. Development builds may include more code for better debugging experience, but modern tools are increasingly optimizing development builds too.

graph LR
    A[Development Mode<br/>npm start] --> B[Full Bundle<br/>Some Optimization<br/>⚡]
    C[Production Build<br/>npm run build] --> D[Heavily Optimized Bundle<br/>Full Tree Shaking<br/>✅]

    style A fill:#fff3e0
    style B fill:#fff3e0
    style C fill:#e8f5e8
    style D fill:#e8f5e8
# Development (minimal tree shaking)
npm start

# Production (aggressive tree shaking)
npm run build

The Bottom Line

Tree shaking is like having a smart packing assistant for your React app. It automatically removes the code you don't need, making your app faster and more efficient for your users.

graph TD
    A[Your React App] --> B[Tree Shaking Process]
    B --> C[Unused Code Removed]
    B --> D[Used Code Kept]
    C --> E[Smaller Bundle Size]
    D --> E
    E --> F[Faster Loading]
    E --> G[Better UX]
    E --> H[Lower Bandwidth]

    style A fill:#e3f2fd
    style B fill:#e8f5e8
    style C fill:#ffebee
    style D fill:#e8f5e8
    style E fill:#e3f2fd
    style F fill:#e8f5e8
    style G fill:#e8f5e8
    style H fill:#e8f5e8

Start with these simple practices:

  1. Use named imports (import { something })

  2. Choose tree-shake friendly libraries

  3. Check your bundle size regularly

  4. Import only what you actually use

Your users will thank you for the faster loading times, and you'll build more efficient React applications without much extra effort.


Remember: Modern React tooling like Create React App, Vite, and Next.js handle most of the tree shaking configuration for you. Focus on writing good import statements, and the tools will do the heavy lifting!