# React Bundle Size Audit Checklist Before You Ship to Production

> A practical React bundle size audit checklist covering analysis tools, common bloat sources, tree-shaking issues, and quick wins before every production release.

- **Published:** 2026-01-17
- **Author:** Clixo
- **Reading time:** 5 min read
- **Tags:** react, bundle-size, performance, checklist, webpack, vite
- **Canonical URL:** https://clixo.sh/blog/react-bundle-size-audit-checklist

A React application that felt fast in local development ships to production and immediately underperforms on mobile. The most common culprit is bundle size — a collection of small decisions that compound into megabytes of JavaScript no user asked for. By the time it shows up in a Lighthouse score, you are already dealing with a production problem.

Running a bundle audit before each significant release prevents that. This checklist covers every area worth checking, in the order that produces the fastest results.

```mermaid
flowchart LR
  A["Generate Bundle Analysis"] --> B["Audit Dependencies"]
  B --> C["Verify Tree Shaking"]
  C --> D["Add Code Splitting"]
  D --> E["Optimize Assets"]
  E --> F["Verify Build Config"]
  F --> G["Set Size Budget"]
```

## Before You Start: Generate a Bundle Analysis

You cannot audit what you cannot see. Generate a visual bundle analysis first.

- **Vite**: Install `rollup-plugin-visualizer`. Add it to `vite.config.js` plugins. Run `vite build`. Open the generated `stats.html`.
- **Webpack / CRA**: Install `webpack-bundle-analyzer`. Run `npm run build -- --stats`, then `npx webpack-bundle-analyzer build/bundle-stats.json`.
- **Next.js**: Use `@next/bundle-analyzer`. Enable it in `next.config.js` and run `ANALYZE=true npm run build`.

Keep the treemap open as you work through the checklist. Every fix should reduce the size of a visible rectangle in the map.

## Dependencies and Third-Party Libraries

- [ ] **Check for duplicate packages.** Run `npm ls <package-name>` for major libraries. Multiple versions of React, lodash, or date libraries in the same bundle are a common problem in monorepos and projects with many dependencies.
- [ ] **Replace moment.js** with `date-fns` or `dayjs` if it appears in the bundle. `moment` does not tree-shake; `date-fns` imports only the functions used.
- [ ] **Audit icon libraries.** Importing from `@heroicons/react` or `react-icons` at the package root pulls in every icon. Import individual icons by path instead: `import { ArrowRight } from "@heroicons/react/24/solid"`.
- [ ] **Check lodash usage.** `import _ from "lodash"` imports the entire library. Use `import debounce from "lodash/debounce"` or switch to native equivalents for simple utilities.
- [ ] **Look for libraries with lighter alternatives.** A full charting library may be 200KB when only one chart type is needed. A date picker library may include internationalization data for every locale.
- [ ] **Verify peer dependencies are not duplicated.** Some dependencies bundle their own copy of React or other shared libraries. Check the bundle map for unexpected duplicates.

## Tree Shaking

- [ ] **Confirm named exports are used correctly.** Tree shaking eliminates unused exports only when imports are static named imports. `import * as lib from "lib"` defeats tree shaking for the entire module.
- [ ] **Check `sideEffects` configuration.** In `package.json`, the `sideEffects` field tells bundlers which files can be safely dropped if their exports are unused. Confirm your own packages and any in-house libraries have this set correctly.
- [ ] **Avoid re-exporting everything from barrel files.** A `index.js` that re-exports every component in a directory forces bundlers to include all of them even when only one is used. Prefer direct imports or split barrel files by feature.

## Code Splitting

- [ ] **Confirm routes are lazy-loaded.** Every top-level route should use `React.lazy`. Check the network panel in the browser: navigating to a new route should trigger a new chunk download.
- [ ] **Identify heavy components that are conditionally rendered.** Modals, drawers, editors, and admin panels that appear on interaction are good candidates for splitting, especially if they import large libraries.
- [ ] **Verify Suspense boundaries and error boundaries are in place.** Every lazy-loaded component needs a `Suspense` wrapper and an error boundary for when chunk fetches fail.

## Assets and Static Files

- [ ] **Check for uncompressed images imported directly into JavaScript.** SVGs imported as React components are fine for small icons but can inflate the bundle if used for large illustrations.
- [ ] **Confirm CSS is not inlined in JS unnecessarily.** CSS-in-JS solutions that serialize styles at render time can add to JavaScript execution cost. Verify this is intentional.
- [ ] **Check font loading strategy.** Fonts loaded via JavaScript rather than CSS or `<link>` tags can block rendering and inflate the JS parse cost.

## Build Configuration

- [ ] **Verify production mode is active.** A React build with `NODE_ENV=development` includes PropTypes, development warnings, and extra checks. Confirm `process.env.NODE_ENV` is set to `"production"` in the production build.
- [ ] **Confirm minification is running.** Check that the output files are minified. A Vite or Webpack production build should produce compressed output by default, but configuration overrides can disable this.
- [ ] **Enable compression.** Static assets should be served with gzip or Brotli compression. This is a server or CDN configuration, not a bundler setting, but it has a larger impact on transfer size than most bundler optimizations.
- [ ] **Check chunk splitting strategy.** By default, Vite and Webpack split vendor dependencies into a separate chunk. Confirm this is happening — vendor chunks can be cached across deployments, reducing repeat load times for returning users.

## After the Audit

- [ ] **Record the baseline bundle sizes before starting.** Compare main chunk size and total transfer size after each fix.
- [ ] **Run Lighthouse in incognito on a throttled connection.** A 150KB reduction on desktop may save 3 seconds on a mobile 3G simulation.
- [ ] **Set a bundle size budget.** Most bundlers support size limits in configuration. Failing the build when a chunk exceeds a threshold prevents regressions from accumulating silently.

A bundle audit is most useful as a recurring practice — run it before major releases and any time a new heavy dependency is added to the project.

If your team needs hands-on help reducing bundle size and improving load performance, [Clixo does full-stack product engineering](https://clixo.sh/#contact), including build optimization and architecture review.

---

Clixo · 1141 W Bryn Mawr Ave, Itasca, IL 60143, US · [hello@clixo.sh](mailto:hello@clixo.sh)
[Start a build](https://clixo.sh/#contact) · [All services](https://clixo.sh/services) · [Agent guide (llms.txt)](https://clixo.sh/llms.txt)
