How to tree-shake in React

Tree-shaking in React removes unused code from production bundles by analyzing ES module imports and eliminating dead code paths. With over 12 years of React experience since 2014 and as the creator of CoreUI, I’ve optimized bundle sizes through proper tree-shaking. Modern bundlers like Webpack and Vite automatically tree-shake ES modules, but proper import patterns are crucial for effectiveness. This approach significantly reduces JavaScript payload by including only code actually used in the application.

Use ES module imports, named imports from libraries, and sideEffects configuration for effective tree-shaking in React.

ES modules for tree-shaking:

// ❌ Bad - CommonJS, cannot tree-shake
const { Button } = require('./components')

// ✅ Good - ES modules, can tree-shake
import { Button } from './components'

// ❌ Bad - imports everything
import * as Components from './components'

// ✅ Good - imports only what's needed
import { Button, Input } from './components'

Named imports from libraries:

// ❌ Bad - imports entire lodash
import _ from 'lodash'
const result = _.debounce(fn, 300)

// ✅ Good - imports only debounce
import { debounce } from 'lodash-es'
const result = debounce(fn, 300)

// ✅ Better - direct path import
import debounce from 'lodash-es/debounce'

// React icons example
// ❌ Bad
import * as Icons from 'react-icons/fa'
<Icons.FaUser />

// ✅ Good
import { FaUser } from 'react-icons/fa'
<FaUser />

Package.json sideEffects:

{
  "name": "my-react-app",
  "sideEffects": [
    "*.css",
    "*.scss"
  ]
}

Component exports for tree-shaking:

// components/index.js
// ❌ Bad - re-exports everything
export * from './Button'
export * from './Input'
export * from './Select'

// ✅ Good - explicit named exports
export { Button } from './Button'
export { Input } from './Input'
export { Select } from './Select'

// Even better - individual files
// import { Button } from './components/Button'

Tree-shakeable utility functions:

// utils/index.js
export const formatDate = (date) => {
  return new Date(date).toLocaleDateString()
}

export const formatCurrency = (amount) => {
  return new Intl.NumberFormat('en-US', {
    style: 'currency',
    currency: 'USD'
  }).format(amount)
}

export const truncate = (str, length) => {
  return str.length > length ? str.substring(0, length) + '...' : str
}

// App.jsx - only formatDate is bundled
import { formatDate } from './utils'

Webpack configuration:

// webpack.config.js
module.exports = {
  mode: 'production',
  optimization: {
    usedExports: true, // Mark unused exports
    minimize: true,    // Remove dead code
    sideEffects: true  // Respect package.json sideEffects
  }
}

Vite tree-shaking:

// vite.config.js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  build: {
    minify: 'terser',
    terserOptions: {
      compress: {
        drop_console: true,
        drop_debugger: true,
        pure_funcs: ['console.log']
      }
    }
  }
})

// Tree-shaking works automatically with ES modules

Conditional code elimination:

// Environment-based tree-shaking
if (process.env.NODE_ENV === 'development') {
  // This code is removed in production build
  console.log('Development mode')
}

// Feature flags
const ENABLE_ANALYTICS = true

if (ENABLE_ANALYTICS) {
  import('./analytics').then(module => module.init())
}
// If ENABLE_ANALYTICS is false, analytics code is tree-shaken

Material-UI tree-shaking:

// ❌ Bad - imports all of MUI
import { Button, TextField } from '@mui/material'

// ✅ Good - direct imports
import Button from '@mui/material/Button'
import TextField from '@mui/material/TextField'

// Or use babel plugin
// .babelrc
{
  "plugins": [
    [
      "babel-plugin-import",
      {
        "libraryName": "@mui/material",
        "libraryDirectory": "",
        "camel2DashComponentName": false
      },
      "core"
    ]
  ]
}

Analyze tree-shaking:

# Build and analyze
npm run build

# Webpack Bundle Analyzer
npm install --save-dev webpack-bundle-analyzer

# package.json
{
  "scripts": {
    "analyze": "source-map-explorer 'build/static/js/*.js'"
  }
}

# Check what's included
npm install -g source-map-explorer
source-map-explorer build/static/js/main.*.js

Dead code example:

// utils.js
export const usedFunction = () => {
  return 'This is used'
}

export const unusedFunction = () => {
  return 'This is never imported'
}

// App.jsx
import { usedFunction } from './utils'

// unusedFunction is tree-shaken from final bundle

React component tree-shaking:

// components/Button.jsx
export function PrimaryButton(props) {
  return <button className="primary" {...props} />
}

export function SecondaryButton(props) {
  return <button className="secondary" {...props} />
}

export function DangerButton(props) {
  return <button className="danger" {...props} />
}

// App.jsx - only PrimaryButton is bundled
import { PrimaryButton } from './components/Button'

function App() {
  return <PrimaryButton>Click</PrimaryButton>
}

Best Practice Note

Use ES modules instead of CommonJS for tree-shakeable code. Import specific named exports, not entire namespaces. Configure sideEffects in package.json for pure modules. Use direct imports from large libraries like lodash-es. Enable usedExports in webpack optimization. Avoid default exports when possible for better tree-shaking. Use webpack-bundle-analyzer to verify tree-shaking effectiveness. This is how we tree-shake CoreUI React applications—ES modules, named imports, and proper bundler configuration reducing bundle size by 30-50% through dead code elimination.


Speed up your responsive apps and websites with fully-featured, ready-to-use open-source admin panel templates—free to use and built for efficiency.


About the Author

Subscribe to our newsletter
Get early information about new products, product updates and blog posts.
How to check if an element is visible in JavaScript
How to check if an element is visible in JavaScript

How to validate an email address in JavaScript
How to validate an email address in JavaScript

How to Merge Objects in JavaScript
How to Merge Objects in JavaScript

How to Use Bootstrap Dropdown in Angular – CoreUI Integration Guide
How to Use Bootstrap Dropdown in Angular – CoreUI Integration Guide

Answers by CoreUI Core Team