Next.js starter your AI actually understands. Ship internal tools in days not weeks. Pre-order $199 $499 → [Get it now]

How to reduce bundle size in JavaScript

Large JavaScript bundles slow page load times and hurt user experience, especially on mobile devices. As the creator of CoreUI with over 25 years of JavaScript experience since 2000, I’ve optimized bundles for frameworks serving millions of users worldwide. The most effective approach combines tree shaking to remove unused code, code splitting to load only what’s needed, and proper minification. These techniques can reduce bundle sizes by 50-80% in typical applications.

Enable tree shaking by using ES6 imports.

// ❌ Imports entire library
import _ from 'lodash'
const result = _.debounce(fn, 300)

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

CommonJS imports (require) include entire modules. ES6 imports with named exports enable tree shaking. Build tools remove unused exports automatically. Always use lodash-es instead of lodash for better tree shaking.

Implementing Code Splitting

Split code into smaller chunks loaded on demand.

// Static import - included in main bundle
import { heavyFunction } from './heavy-module'

// Dynamic import - loaded when needed
button.addEventListener('click', async () => {
  const { heavyFunction } = await import('./heavy-module')
  heavyFunction()
})

Static imports bundle everything upfront. Dynamic imports create separate chunks. The browser loads chunks only when executed. This reduces initial bundle size significantly.

Analyzing Bundle Size

Use webpack-bundle-analyzer to identify large dependencies.

npm install --save-dev webpack-bundle-analyzer
// webpack.config.js
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin

module.exports = {
  plugins: [
    new BundleAnalyzerPlugin()
  ]
}

The analyzer shows a treemap of your bundle. Identify unexpectedly large dependencies. Look for opportunities to replace heavy libraries with lighter alternatives. Focus optimization efforts on the largest chunks.

Removing Unused Dependencies

Audit and remove packages not actually used.

npm install -g depcheck
depcheck

Depcheck finds unused dependencies. Remove them from package.json. Ensure imports actually exist in code. Regular audits prevent dependency bloat over time.

Using Production Builds

Enable optimizations in production mode.

// webpack.config.js
module.exports = {
  mode: 'production',
  optimization: {
    minimize: true,
    usedExports: true
  }
}

Production mode enables minification and tree shaking. The usedExports option marks unused exports. The minimize option runs terser for compression. Always build for production before deployment.

Replacing Heavy Libraries

Swap large libraries for lighter alternatives.

// ❌ moment.js (67 KB minified)
import moment from 'moment'
const date = moment().format('YYYY-MM-DD')

// ✅ date-fns (5-15 KB with tree shaking)
import { format } from 'date-fns'
const date = format(new Date(), 'yyyy-MM-dd')

Moment.js is monolithic and heavy. Date-fns allows importing individual functions. Many libraries have lightweight alternatives. Research before adding dependencies.

Best Practice Note

This is the same bundle optimization strategy we use in CoreUI to keep the library performant. Measure before optimizing - use tools like Lighthouse and Chrome DevTools Coverage tab. Set performance budgets and fail builds that exceed them. Lazy load routes, heavy components, and rarely-used features. Consider using preact instead of React for smaller bundles. Compress assets with gzip or brotli on the server. Every kilobyte matters for mobile users on slow connections.


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