Create React App (CRA) has served the React community well since 2016—but its time is up. With CRA now officially End-of-Life (EOL) and modern frontend tooling racing ahead, Vite has emerged as the go-to alternative for lightning-fast builds, modern features, and developer joy.
If you’re still using CRA, now is the perfect time to upgrade your setup. In this post, we’ll walk you through how to migrate your React project from CRA to Vite using current best practices (2025 edition).
CRA was great for its time, but it’s no longer keeping up with the modern frontend ecosystem. Here’s what you get with Vite:
- Blazing fast dev server with hot module replacement (HMR)
- Instant startup time (native ES modules, pre-bundling with esbuild)
- Simpler configuration using
vite.config.js
- First-class TypeScript and JSX support
- Built-in support for PostCSS, CSS Modules, SCSS, etc.
- Modern plugin ecosystem and SSR-ready
Step-by-Step: CRA → Vite Migration
Let’s get your project migrated. Here’s how to do it.
1. Clean Up CRA-Specific Files
CRA has some tooling that’s not needed in a Vite setup.
rm -rf node_modules
rm package-lock.json yarn.lock # depending on package manager
Uninstall CRA dependencies:
npm install --save-dev vite @vitejs/plugin-react
Delete any files specific to CRA like:
serviceWorker.js
(if not using it)setupTests.js
(if unused or custom setup)
2. Install Vite and Base Dependencies
Install Vite and its React plugin:
npm install --save-dev vite @vitejs/plugin-react
Update your package.json
scripts:
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
}
3. Add vite.config.js
Create a vite.config.js
at the root:
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
});
If you use TypeScript, you can use vite.config.ts
.
4. Adjust Project Structure (If Needed)
CRA has a default assumption about public/index.html
. Vite handles HTML differently.
Create a new index.html
at the root (not inside public
):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>
Your entry point file should now be src/main.jsx
or src/main.tsx
with this content:
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import './index.css';
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<App />
</React.StrictMode>
);
5. Handle Static Assets
In CRA, static assets go in the public/
folder. Vite also supports this, but remember:
- Only static assets that are NOT imported in JS/TS go in
public/
. - If you import images directly, they’ll be processed by Vite’s asset pipeline.
6. Migrate Environment Variables
CRA uses REACT_APP_
prefix. Vite uses VITE_
.
Update your .env
:
VITE_API_URL=https://api.example.com
Access them in code like:
import.meta.env.VITE_API_URL
7. Testing Setup
CRA often comes with Jest out of the box. If you’re using Jest, you can keep it—or consider switching to Vitest, which integrates seamlessly with Vite.
Install Vitest (optional):
npm install --save-dev vitest @testing-library/react @testing-library/jest-dom
Update vite.config.js
:
test: {
globals: true,
environment: 'jsdom',
},
8. Final Checks
- Lint your project.
- Run
npm run dev
and check for console errors. - Make sure build (
npm run build
) and preview (npm run preview
) work smoothly.
You’re Done!
You’ve successfully migrated your project from Create React App to Vite. Your builds will be faster, your config simpler, and your developer experience modernized.
What’s Next?
- Explore Vite plugins for things like SVG, PWA, GraphQL, etc.
- Enable code splitting, lazy loading, and SSR if needed.
- Consider moving to Vitest + Playwright for full modern testing.
Leave a Reply