How to Migrate from Create React App to Vite

For years, Create React App (CRA) was the industry standard for initializing React applications. However, CRA relies on Webpack, which bundles the entire application before starting the local development server. As codebases grow, local startup times can balloon to minutes, and hot module replacement (HMR) can take several seconds to reflect simple code changes.

Vite takes a radically different approach: it leverages native ES modules (ESM) in the browser to serve files on demand during development, and uses Rollup for highly optimized production builds. This guide provides a complete roadmap to successfully migrate your project from CRA to Vite, slashing your build times and improving developer experience.

Why Migrate to Vite?

The benefits of migrating away from Create React App go beyond build speeds. Create React App is officially deprecated, meaning it no longer receives updates or optimizations for modern React features. By adopting Vite, you gain several engineering advantages:

  • Near-Instant Server Starts: Vite starts the dev server immediately, regardless of application size, by delegating bundling to the browser using native ES modules.
  • Lightning-Fast HMR: Code changes are compiled almost instantly, updating only the modified module without reloading the entire page or losing application state.
  • Modern Config: Vite replaces complex Webpack configs and ejecting workarounds with a simple, declarative configuration file.

Step 1: Dependency Updates

To begin the migration, you need to remove the deprecated react-scripts package and install Vite along with its React plugins. Run the following command in your terminal:

npm uninstall react-scripts
npm install --save-dev vite @vitejs/plugin-react

If your project uses TypeScript, you should also install the Vite TypeScript plugin or ensure you have TypeScript set up. If you prefer using SWC (Speedy Web Compiler) for compiling React components, you can install @vitejs/plugin-react-swc instead of the standard Babel-based plugin, which provides even faster compilation speeds.

Step 2: Configuration

Create a file named vite.config.js (or vite.config.ts if using TypeScript) in the root of your project directory. This file replaces all Webpack configurations and eject settings. Add the following basic configuration:

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';

export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
    },
  },
  server: {
    port: 3000,
    open: true,
  },
});

This configuration registers the React plugin, sets up a convenient path alias (@ mapping to the /src directory), and configures the dev server to run on port 3000 and automatically open the browser on launch.

Step 3: Relocate and Update index.html

In a Create React App project, the index.html template is stored in the public/ folder. Webpack injects the built scripts into it during the compilation phase.

Vite treats index.html as the entry point of the application and expects it to reside in the project root directory. Move index.html from /public to the root folder, and apply the following changes:

  • Remove any occurrences of %PUBLIC_URL% from your asset paths (e.g., replace href="%PUBLIC_URL%/favicon.ico" with href="/favicon.ico").
  • Inject a script tag inside the <body> element to point to your main application entry point (usually /src/index.js or /src/index.tsx).
<!-- Inside index.html, right before </body> -->
<script type="module" src="/src/index.tsx"></script>

Step 4: Environment Variables

Create React App references environment variables prefixed with REACT_APP_ and accesses them via process.env. Vite handles environment variables differently to avoid polluting the global namespace.

It requires variables to be prefixed with VITE_ and exposes them through import.meta.env. To migrate your environment variables:

  • Rename all instances of REACT_APP_API_URL to VITE_API_URL in your .env files.
  • Search and replace all references in your code from process.env.REACT_APP_API_URL to import.meta.env.VITE_API_URL.

If you have TypeScript files, you should create a src/vite-env.d.ts file containing type definitions for your environment variables to ensure typescript compilation passes without errors:

/// <reference types="vite/client" />

interface ImportMetaEnv {
  readonly VITE_API_URL: string;
}

interface ImportMeta {
  readonly env: ImportMetaEnv;
}

Step 5: TypeScript and Compiler Configurations

Vite compiles files individually using Esbuild, which runs significantly faster than the traditional TypeScript compiler (tsc). However, Esbuild does not perform type checking.

To avoid deploying type errors, you must adjust your tsconfig.json and run a type check command in your build scripts. Make sure your tsconfig.json includes the following compiler options:

  • "target": "ESNext": Targets modern Javascript runtimes.
  • "module": "ESNext": Enables standard ES Module imports.
  • "moduleResolution": "Bundler" or "Node": Matches how Vite resolves module paths.
  • "isolatedModules": true: Ensures files can be safely compiled individually by Esbuild.

Then, update your package build command to perform type-checking before bundling: "build": "tsc --noEmit && vite build". This step ensures compile errors are caught before deploying code.

Step 6: CSS, Assets, and SVG Handling Differences

Webpack handles asset loading transparently, allowing developers to import SVGs directly as React components. Vite uses a more standard approach. If you import an image or SVG file, Vite returns the public URL path.

To preserve your ReactComponent SVG imports, you need to use a plugin like vite-plugin-svgr. Install the plugin and add it to your vite.config.js under the plugins array. For CSS modules, Vite provides out-of-the-box support for files ending in .module.css, mapping classes automatically without configuration.

For custom web fonts or large media files in your CSS, make sure paths are relative to the stylesheet or stored in the /public directory. Vite serves any assets in the /public folder directly at the root, making them accessible via absolute paths. Transitioning your assets correctly guarantees that references remain intact when compiling the production bundle.

Vite and Build Pipe Optimization at the Edge with Bramsley

DevOps Acceleration: Modernizing local development setups and bundling pipelines requires meticulous care to prevent dependency breakdown. Bramsley Digital Studio bridges this gap by seamlessly migrating legacy configurations to Vite and esbuild, optimizing web assets, and deploying fast caching networks to ensure build times and live loads remain sub-second.

Bramsley Digital Studio

Enterprise Digital Architecture

We engineer digital infrastructure that drives measurable B2B growth. Experts in Legacy System Migration and High-Performance Frontends.

Architecture Specs & Case Studies

Scale Your Operations

  • Legacy System Migration
  • Scalable Infrastructure
  • High-Performance Frontends
  • Global Edge Deployment