Back to blog
Performance·June 28, 2024

From 6MB to Under 2MB: How We Migrated Eight Production SPAs from Webpack to Vite

Eight production SPAs. Bloated bundles pushing 6MB. Build times that killed developer momentum. Here's how we diagnosed the problem, made the call to migrate to Vite, and shipped all eight apps with zero downtime.

When the Build Becomes the Problem

There's a particular kind of technical debt that's easy to ignore because it doesn't break anything — it just makes everything slower and slightly worse. Aging Webpack configs fall into this category. They work, technically. But they accumulate complexity over time, nobody fully understands them anymore, and they impose a hidden tax on every developer who has to wait through a build.

At Guild Mortgage, eight production single-page applications had reached this point. Bundle sizes were bloated — some pushing 6MB. Cold-start build times were slow enough to interrupt flow. And the developer experience had become a low-grade source of daily friction that nobody was addressing because the path forward wasn't obvious.

We made it obvious.

Why Vite

The decision to migrate to Vite rather than optimize the existing Webpack configs came down to one core insight: Webpack's approach to bundling made it inherently difficult to reason about what was being included and why. Dependencies were opaque. Tree shaking was inconsistent. The tooling required to diagnose problems (webpack-bundle-analyzer, custom plugins) added more configuration on top of an already complex setup.

Vite's native ES module support inverts this. In development, dependencies are served as individual modules — you can see exactly what's being pulled in. That transparency alone changed how the team reasoned about performance. It also made Vite's production builds meaningfully faster because the optimization surface was cleaner from the start.

How We Approached It

The first step was measurement, not cutting. We ran webpack-bundle-analyzer across all eight applications to get a precise picture of where the weight was coming from before touching anything. This prevented the trap of optimizing things that didn't matter while missing the things that did.

The findings were predictable once we looked: large routes loading everything upfront, whole-library imports pulling in far more than was needed, and assets being bundled that had no business being in the JavaScript payload at all.

From there, the remediation was systematic:

Route-level code splitting using React.lazy() and Suspense — large routes only loaded when actually navigated to. This alone had an outsized impact on initial load time.

Targeted imports replaced whole-library imports. Whole-library pulls like lodash were swapped for targeted ones like lodash/debounce. Every import became intentional.

moment.js was replaced entirely with date-fns — a significantly lighter library that's tree-shakeable by design. Moment had been the right choice once. It hadn't been for a long time.

Large assets — images, SVGs that didn't need to be inlined — were moved to the public folder rather than processed through the bundle.

Production mode was enforced across all builds. This sounds obvious, but enforcing it consistently activated automatic tree-shaking that had been silently disabled in some environments.

The Outcome

Bundles that sat at 6MB dropped to under 2MB. Cold-start build times fell sharply. Core Web Vitals improved across all eight applications. And perhaps most importantly, the team could iterate quickly without dreading the build step — that hidden daily friction disappeared.

All eight applications were migrated with zero downtime.

What This Was Really About

The technical work here was straightforward. The harder part was making the call to invest in it — to treat the build pipeline as a product worth improving rather than infrastructure to be tolerated. Developer experience is a performance metric. When engineers can move faster and with more confidence, better software ships more often.

The Webpack-to-Vite migration was worth doing. It would have been worth doing a year earlier.

Marcus

Marcus Bass

AI · Career Q&A

get in touch