Migrating to Vite: How We Made Our React App 10x Faster with Less Configuration

Migrating to Vite: How We Made Our React App 10x Faster with Less Configuration

Introduction

In my current position, we were using Webpack to bundle our React application. While Webpack is a powerful and flexible bundler, we started facing performance bottlenecks that were slowing down development. Long startup times, slow hot module replacement (HMR), and the complexity of managing Webpack’s configuration became increasingly frustrating.

We decided to explore Vite as an alternative, and the results were impressive. In this post, I’ll walk through why we migrated, how we did it, and the challenges we faced along the way.


Why Migrate?

Webpack Pain Points

  1. Slow Startup Time: Our project had grown significantly, and Webpack’s cold start was taking over 30 seconds.
  2. Slow Rebuilds: Even minor changes took several seconds to reflect in the browser, making the feedback loop painful.
  3. Complex Configuration: Custom loaders, plugins, and optimizations made our Webpack config difficult to maintain.
  4. HMR Performance Issues: Hot module replacement was unreliable, often requiring full reloads.

Vite Advantages

  1. Instant Dev Server: Vite serves files directly via native ES modules, eliminating bundling overhead in development.
  2. Lightning-Fast HMR: Updates are almost instant, even for large applications.
  3. Simplified Configuration: Vite works with sensible defaults, reducing the need for custom loaders and plugins.
  4. Optimized Build Output: Uses Rollup under the hood for efficient production builds.

Given these benefits, we decided to move forward with the migration.


Migration Process

1. Assessing Compatibility

Before switching, we checked our dependencies for any Webpack-specific configurations:

  • Aliases (e.g., resolve.alias in Webpack vs. resolve.alias in Vite).
  • Environment Variables (e.g., process.env vs. import.meta.env).
  • Plugins and Loaders (some Webpack plugins required Vite-friendly alternatives).

2. Installing Vite

We started by adding Vite and its React plugin:

yarn add -D vite @vitejs/plugin-react

Then, we updated our package.json scripts:

Note: Vite supports using ES modules syntax in the config file even if the project is not using native Node ESM, e.g., type: "module" in package.json. In this case, the config file is auto pre-processed before load.

3. Configuring Vite

We replaced our Webpack configuration with a new vite.config.ts file:

  • Create a file named vite.config.ts
  • Add the basic configuration:

If you need to run on a specific port or host by default, or set up aliases for cleaner imports:

4. Handling Webpack-Specific Features

  • Aliases: Webpack’s resolve.alias needed to be converted to Vite’s format.
  • Environment Variables: We replaced process.env with import.meta.env and renamed variables prefixed with REACT_APP_ to VITE_.
  • CSS Handling: Vite has built-in support for PostCSS, so we removed unnecessary CSS loaders.
  • Plugins: We replaced Webpack plugins with equivalent Vite/Rollup plugins.

4.1 Adapting index.html

  • Ensure the index.html file is in the root path of the project.
  • All files stored in /public are served as / (e.g., /public/favicon.png is accessible as /favicon.png).
  • Adjust paths to load the index.tsx file correctly:

5. Testing and Debugging

We also migrated to Vitest for better compatibility with Vite, allowing us to remove all Babel dependencies as well. This simplified our setup and improved test performance.

We ran vite dev and fixed issues as they arose. Some common adjustments included:

  • Ensuring all dependencies were compatible with Vite’s ES module approach.
  • Fixing missing polyfills for older browsers.
  • Adjusting TypeScript settings to align with Vite’s expectations.

Challenges and Solutions

During the migration, we encountered a few roadblocks:

  1. Some Dependencies Didn’t Support ES Modules→ We used vite-plugin-commonjs to handle CommonJS dependencies.
  2. Polyfills for Node.js Modules Were Missing→ We added manual polyfills for buffer, crypto, and other Node.js APIs where needed.
  3. HMR Didn’t Work Initially for Certain Components→ We ensured dependencies weren’t mistakenly placed in node_modules, preventing them from being handled by Vite’s HMR.

Performance Gains & Final Thoughts

After migrating, we saw immediate improvements:

  • Dev server startup time dropped from 30s to under 2s.
  • HMR updates were almost instant.
  • Build times were 10x faster, and the entire CI/CD pipeline execution time was reduced by 2x.

Switching to Vite was a game-changer for our project. If you're struggling with Webpack’s speed and complexity, I highly recommend considering Vite. The migration was smoother than expected, and the developer experience has been vastly improved.


Have you migrated from Webpack to Vite? What challenges did you face? Let me know in the comments!