the step by step guide
Create React App is no longer maintained, but an existing project does not migrate itself. Whoever migrates Create React App to Vite has to transfer configuration, environment variables, proxy setup and tests one by one to end up with a faster dev server and no broken builds.
Table of Contents
- 1. Why migrating Create React App to Vite is necessary now
- 2. Preparation: dependencies and the base setup
- 3. vite.config.ts instead of react-scripts
- 4. Environment variables from REACT_APP to VITE
- 5. Moving index.html, the public folder and assets
- 6. Proxy setup for local API development
- 7. Migrating Jest to Vitest
- 8. Common pitfalls after the migration
- 9. Create React App and Vite compared directly
- 10. Summary
- 11. FAQ
1. Why migrating Create React App to Vite is necessary now
Create React App has been officially archived, no longer receives updates for new React versions, and is no longer recommended by the React documentation. Whoever runs an existing application will sooner or later have to migrate Create React App to Vite, because react-scripts internally builds on outdated versions of Webpack, Babel and ESLint, which accumulate security vulnerabilities and eventually stop being maintained.
The second driver is developer experience. The dev server of Create React App often takes several seconds to start for mid sized projects, with noticeable delays for hot module replacement. Vite uses native ES modules in the browser during development and therefore usually starts in under a second, which is immediately noticeable on every save.
The third reason: many modern libraries now test and document their setup guides exclusively for Vite, while Create React App setups often only survive as community workarounds. Whoever migrates Create React App to Vite also regains access to current documentation and community support for new tools.
2. Preparation: dependencies and the base setup
Before the actual migration, it pays off to take stock of every react-scripts specific feature in the project: environment variables with the REACT_APP_ prefix, proxy configuration in package.json, as well as CRACO or react-app-rewired overrides if the project has already customized the Webpack configuration. This list determines the actual migration effort far more than pure project size.
Vite is then installed alongside react-scripts, so both toolchains can coexist in the same repository for a transition period. This allows testing the new dev server while the existing build keeps working, until the migration is fully complete.
# Install Vite and the React plugin alongside the existing CRA toolchain
npm install --save-dev vite @vitejs/plugin-react
# Vitest replaces Jest as the test runner in a later step
npm install --save-dev vitest @vitest/ui jsdom
# react-scripts, react-app-rewired or craco can be removed once
# vite.config.ts fully replaces their functionality
npm uninstall react-scripts
3. vite.config.ts instead of react-scripts
The core of the migration is the new vite.config.ts, which replaces everything that was previously hidden implicitly inside react-scripts. While Create React App had no visible configuration file, Vite makes every setting explicit, which initially means more code, but is considerably easier to debug long term because nothing hides in a black box anymore.
// vite.config.ts: explicit replacement for the hidden react-scripts config
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'node:path';
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
// Mirrors a CRA jsconfig.json "baseUrl": "src" setup
'@': path.resolve(__dirname, './src'),
},
},
server: {
port: 3000, // Match the old CRA default port for a familiar dev workflow
open: true,
},
build: {
outDir: 'build', // Keep the output directory CI/CD pipelines already expect
sourcemap: true,
},
});
Whoever migrates Create React App to Vite and previously used CRACO or react-app-rewired can consolidate all overrides into this one file, instead of managing them through a separate overrides package. This often reduces the number of build tool dependencies in the project by two to three packages.
4. Environment variables from REACT_APP to VITE
Create React App expects environment variables with the REACT_APP_ prefix, accessible via process.env.REACT_APP_API_URL. Vite instead uses the VITE_ prefix and exposes the values through import.meta.env.VITE_API_URL. This rename affects every place in the code that accesses environment variables and is most reliably handled with a project wide search and replace operation.
# .env file: rename the prefix from REACT_APP_ to VITE_
# BEFORE (Create React App)
REACT_APP_API_URL=https://api.example.com
REACT_APP_FEATURE_FLAG_NEW_CHECKOUT=true
# AFTER (Vite)
VITE_API_URL=https://api.example.com
VITE_FEATURE_FLAG_NEW_CHECKOUT=true
# Search and replace across the codebase:
grep -rl "process.env.REACT_APP_" src/ \
| xargs sed -i 's/process\.env\.REACT_APP_/import.meta.env.VITE_/g'
A common mistake during this migration: developers forget that import.meta.env, unlike process.env, is only statically replaced at build time and does not allow dynamic keys. Access like import.meta.env[dynamicKey] does not work reliably and must be replaced with explicit, statically known variable names.
5. Moving index.html, the public folder and assets
In Create React App, index.html lives in the public folder and is treated by Webpack as a template that replaces placeholders like %PUBLIC_URL%. With Vite, index.html moves to the project root and becomes the entry point of the build process itself, including a direct <script type="module" src="/src/main.tsx"> tag instead of a Webpack injected bundle.
The public folder remains in Vite for static assets meant to be copied unchanged, but %PUBLIC_URL% placeholders must be replaced with relative paths, because Vite does not know this Webpack specific templating. Images and fonts previously imported from src keep working unchanged in Vite, since both tools support the ES module import system for assets.
6. Proxy setup for local API development
Many Create React App projects use the simple "proxy": "http://localhost:8080" field in package.json to forward API requests to a backend during local development. Vite offers a considerably more flexible, but also more explicit, proxy configuration directly in the server block of vite.config.ts, allowing different targets per path prefix.
// vite.config.ts: proxy replaces the simple "proxy" field from package.json
export default defineConfig({
server: {
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
},
'/ws': {
target: 'ws://localhost:8080',
ws: true, // WebSocket proxying needs to be enabled explicitly
},
},
},
});
7. Migrating Jest to Vitest
React Testing Library tests barely change when porting from Jest to Vitest, because Vitest deliberately provides a compatible API. The test functions describe, it and expect stay identical, which makes migrating the tests themselves the easiest subtask when migrating Create React App to Vite. The more involved part is the Jest configuration, which needs to be translated into a test section of vite.config.ts.
Mock functions with jest.mock() get replaced by vi.mock(), and global mock functions like jest.fn() become vi.fn(). A project wide search and replace handles most of these renames automatically, while more complex mock setups with module hoisting need manual adjustment.
8. Common pitfalls after the migration
The most common mistake after migrating Create React App to Vite concerns absolute imports that previously worked through jsconfig.json or tsconfig.json with baseUrl. Vite does not automatically read this TypeScript specific configuration for runtime module resolution, which is why the alias configuration must additionally be duplicated in vite.config.ts, as shown in the example in section three.
A second pitfall involves CSS modules and global stylesheets, which in rare cases produce different naming conventions for generated classes between Webpack and Vite. Visual regression tests before and after the migration reliably catch such differences before they become visible in production.
9. Create React App and Vite compared directly
The table below summarizes the concrete differences relevant in practice when migrating Create React App to Vite.
| Aspect | Create React App | Vite | Impact |
|---|---|---|---|
| Dev server start | Several seconds | Under one second | Native ES module serving |
| Environment variables | REACT_APP_ prefix | VITE_ prefix | Project wide rename needed |
| Configuration | Hidden in react-scripts | Explicit in vite.config.ts | Better debuggability |
| Test runner | Jest | Vitest, compatible API | Tests run almost unchanged |
| Maintenance status | Archived, no updates | Actively developed | Long term safety |
The table shows that migrating Create React App to Vite is not a pure performance upgrade, it also secures long term maintainability. An archived build tool with no security updates is a growing risk for production applications, which clearly justifies the migration.
Mironsoft
React build tooling, Vite migrations and CI/CD modernization
Still running on an archived Create React App setup?
We transfer your configuration, environment variables and tests from Create React App to Vite and future proof your build against upcoming React versions.
Migration Audit
Inventory of all CRACO, rewire and proxy configurations
Vite Setup
Complete vite.config.ts with alias, proxy and build settings
Test Relocation
Jest to Vitest migration including mock functions and CI pipeline
10. Summary
Whoever wants to migrate Create React App to Vite should start with an inventory of every react-scripts specific feature: environment variables, proxy configuration and any CRACO overrides. The new vite.config.ts makes everything explicit that was previously implicit, environment variables move from the REACT_APP_ to the VITE_ prefix, and index.html itself becomes the entry point instead of a template in the public folder.
Proxy configuration, test relocation from Jest to Vitest, and alias resolution for absolute imports are the parts requiring the most care. The payoff of the migration is a dev server that starts in under a second, and a build tool that, unlike the archived Create React App, is actively developed and keeps pace with new React versions.
Migrating Create React App to Vite: The Essentials
Configuration
vite.config.ts replaces react-scripts, CRACO and react-app-rewired in a single file.
Environment variables
REACT_APP_ becomes VITE_, process.env becomes import.meta.env throughout the code.
Tests
Vitest offers a Jest compatible API, test functions stay largely unchanged.
Result
Dev server starts in under a second instead of several, an actively maintained build tool.