DEV Community

Cover image for How I Split a 450 kB React Entry Bundle into Optimized Chunks with Vite.
Sanket Chaudhari
Sanket Chaudhari

Posted on

How I Split a 450 kB React Entry Bundle into Optimized Chunks with Vite.

How I Split a 450 kB React Entry Bundle into Optimized Chunks with Vite

Lazy Loading • Code Splitting • Performance Optimization

While building my personal portfolio, I kept adding features such as animations, a floating chatbot, a command palette, a resume viewer, and even a small 2048 game.

Eventually, I started asking myself one question:

How much of my application is actually being downloaded when someone opens my website?

Instead of guessing, I analyzed the production build, visualized the bundle, and optimized it using Vite's manual chunking.


The Problem

Every new feature increased the production bundle size.

The application worked perfectly, but the initial entry bundle had become much larger than I wanted.

📷 Screenshot 1

Figure 1: Production build before optimization.

The build itself wasn't alarming, but it raised an important question:

Where was all this code coming from?

Simply looking at the bundle size wasn't enough. I wanted to understand which libraries and components were contributing the most to the production build before making any changes.

Instead of optimizing blindly, I decided to inspect the bundle visually.


Understanding the Bundle

To analyze the production output, I used rollup-plugin-visualizer, which generates an interactive treemap of the final bundle.

The visualization immediately highlighted where most of the JavaScript was coming from.

Some of the largest contributors were:

  • React & React DOM
  • Framer Motion
  • Lucide Icons
  • My application code

Having this visual breakdown made it much easier to identify what could be separated into dedicated vendor chunks.

📷 Screenshot 2

Figure 2: Bundle visualization generated using Rollup Plugin Visualizer.

One thing immediately stood out: framework libraries and application code were bundled together more than I wanted.

Instead of shipping everything through the initial entry bundle, I decided to split the build into smaller, cache-friendly chunks.


The Optimization

After identifying the largest dependencies, I reorganized how Vite generated the production build.

Instead of placing every dependency into a single vendor bundle, I grouped related libraries into dedicated chunks.

This makes the initial application lighter while allowing browsers to cache framework libraries separately from my own code.

Here's the manualChunks() configuration I used:

manualChunks(id) {
  if (id.includes("node_modules")) {

    if (
      id.includes("react-dom") ||
      id.includes("react-router") ||
      id.includes("scheduler")
    ) {
      return "vendor-react";
    }

    if (id.includes("framer-motion")) {
      return "vendor-framer";
    }

    if (id.includes("lucide-react")) {
      return "vendor-lucide";
    }

    return "vendor-others";
  }
}
Enter fullscreen mode Exit fullscreen mode

Instead of one large bundle, the build now generates multiple optimized chunks.

  • vendor-react → React, React DOM and routing libraries
  • vendor-framer → Framer Motion
  • vendor-lucide → Lucide Icons
  • vendor-others → Remaining third-party dependencies

This structure keeps the application code separate from framework libraries, making future updates and browser caching more efficient.


The Results

After applying manual chunking, I generated another production build.

The difference was immediately visible.

📷 Screenshot 3

Figure 3: Production build after manual chunking.

Compared with the previous build, the application's entry bundle became significantly smaller while framework libraries were moved into dedicated vendor chunks.

Metric Before After
Entry Bundle 449.65 kB 54.72 kB
Modules 383 353
Build Time 596 ms 383 ms

It's important to note that these numbers refer to the entry bundle, not the total size of every JavaScript asset generated by the build.

The optimization focused on splitting framework libraries into dedicated chunks, reducing the amount of code required for the initial application load.


Lessons Learned

This optimization taught me a few valuable lessons.

Measure before optimizing

It's easy to assume what's slowing down an application, but assumptions rarely help. Analyzing the production build and visualizing the bundle showed exactly where optimization efforts should be focused.

Bundle visualization removes the guesswork

The treemap made it clear which libraries occupied the most space. Instead of blindly changing configurations, I could make decisions based on actual build output.

Performance is about loading strategy

The objective wasn't simply to reduce file sizes. The real improvement came from reducing the size of the initial entry bundle and separating framework libraries into dedicated vendor chunks.

Keep measuring

Every new dependency affects the production build. I'll continue monitoring bundle size as the portfolio evolves instead of treating optimization as a one-time task.


Final Thoughts

This optimization gave me a much better understanding of how modern React applications are bundled and delivered.

Using Vite's manual chunking, production build analysis, and bundle visualization helped me reorganize the application into a more maintainable and cache-friendly structure.

There's always more to improve, but this was a valuable step toward building faster, more efficient frontend applications.


Tools Used

  • React
  • TypeScript
  • Vite
  • Rollup Plugin Visualizer

References


Thanks for Reading! 🚀

If you've worked on bundle optimization or React performance, I'd love to hear what techniques worked best for you.

Feel free to share your thoughts or suggestions in the comments.

Connect With Me

🌐 Portfolio: https://yourportfolio.com

If you're interested in interactive frontend projects, AI applications, or full-stack development, feel free to explore my work.

💻 GitHub: https://github.com/sanket1035

💼 LinkedIn: https://linkedin.com/in/sanketchaudhari1035

Top comments (0)