How To Convert CRA To Vite
Introduction
This article explains how to transition your project from Create React App (CRA) to Vite. I want to share my experience and the benefits of making this switch.
In my own development work, I experienced significant performance issues with Create React App, especially in these areas:
- Slow project startup: Starting a development server in CRA took a considerably long time, especially for larger projects. Waiting for Webpack to bundle everything could take several minutes, which wasted time that could have been spent building.
- Slow package installation: Installing new packages in a CRA project could take time because of the large number of dependencies CRA manages. This often resulted in longer wait times during development.
When I switched to Vite, the improvement was immediately noticeable:
- Instant development server startup: Vite's development server starts almost instantly. That means I can start coding and see changes immediately.
- Faster package installation: Vite has fewer dependencies compared to CRA, which results in faster package installation times.
One primary reason for this change is that CRA stopped receiving major updates and was deprecated by the React team in 2023.
To avoid future issues, I transitioned from CRA to Vite and started taking advantage of these modern improvements to keep projects fast, efficient, and easy to maintain.
Prerequisites
Before starting the conversion from Create React App to Vite, make sure the following requirements are in place.
-
Node.js and npm
Ensure you have Node.js and npm installed on your system, preferably version
14.xor higher, since Vite requires Node.js14.18+. I was using Node.js version20.7.0. You can verify your installation with:node -v npm -v -
Basic understanding of Vite
I started the conversion by first familiarizing myself with Vite's basics by reading the official Vite documentation. You can also create a fresh Vite project to understand the differences in structure between Vite and CRA.
-
Back up your project
Before making significant changes, create a backup of your current CRA project to prevent data loss. You can do this by copying the entire project directory to a safe location or by using version control such as GitHub.
-
Install Vite
You will need to install Vite and its dependencies in your project. This can be done through npm or yarn once you begin the conversion.
-
Understand your project structure
Have a good understanding of your current CRA project structure, including configuration files, entry points, and where static assets are located. This will make the migration much smoother.
Once these prerequisites are in place, you are ready to start converting your CRA project to Vite.
Steps for Conversion
1. Set Up Vite
First, set up a new Vite project within your existing CRA project. Start with these steps:
-
Install Vite
Navigate to your CRA project directory and install Vite along with the necessary Vite plugin for React:
npm install vite @vitejs/plugin-react -
Update
package.jsonscriptsSince Vite will handle the build and development processes,
react-scriptsare no longer needed. Remove it from your project:npm uninstall react-scriptsUpdate the
scriptssection in yourpackage.jsonso it uses Vite instead of CRA:"scripts": { "start": "PORT=3000 NODE_ENV=development vite", "start-secure": "NODE_ENV=development && HTTPS=true vite", "build": "tsc && vite build", "preview": "vite preview" }If you already use ESLint and Prettier, you can also add:
"format": "npx prettier --write .", "lint": "eslint '*/**/*.{js,ts,tsx}' --quiet --fix"
2. Configure Vite
Create a vite.config.ts file in the root of your project and configure Vite
for your React setup. To stay as close to CRA as possible, I set the build
directory to build instead of dist and used port 3000 for development:
import react from '@vitejs/plugin-react'
import path from 'path'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
},
},
build: {
outDir: './build',
},
server: {
port: 3000,
},
})
3. Update index.html
In Vite, the entry HTML file should live in the root directory. Move your CRA
public/index.html file to the project root and update the script reference.
- Move
public/index.htmlto the project root. - Modify the
<script>tag so it points to the Vite entry file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no, maximum-scale=1, user-scalable=no"
/>
<link rel="shortcut icon" href="/favicon.svg" />
<meta name="description" content="My Vite App Description" />
<title>My Vite App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>
4. Adjust Project Structure
Ensure that your index.ts or index.tsx file is in the src directory and
rename it to main.tsx so it matches the script reference in index.html.
5. Update Imports
I used path aliases to keep import statements cleaner and more maintainable. In
the vite.config.ts example above, the @ alias points to ./src, so you can
import files like this:
import MyComponent from '@/components/MyComponent'
6. Migrate Static Assets
Vite handles static assets differently than CRA. Move your static assets from
the public folder to src/assets and update import paths in the relevant
components.
For example, if you have an image in public/images/logo.png, move it to
src/assets/images/logo.png and update the import:
import logo from './assets/images/logo.png'
7. Install Necessary Plugins
Vite has a plugin system similar to CRA's Webpack configuration. Install any necessary plugins to support the features your project depends on, such as environment variables, CSS preprocessing, or other build-time needs.
8. TypeScript Configuration
To use TypeScript, you will need to configure both tsconfig.json and
tsconfig.node.json.
-
tsconfig.jsonCreate a
tsconfig.jsonfile in the root of your project with the following configuration:{ "compilerOptions": { "target": "ESNext", "useDefineForClassFields": true, "lib": ["DOM", "DOM.Iterable", "ESNext"], "allowJs": true, "skipLibCheck": true, "esModuleInterop": true, "noFallthroughCasesInSwitch": true, "allowSyntheticDefaultImports": true, "strict": true, "forceConsistentCasingInFileNames": true, "module": "ESNext", "moduleResolution": "Node", "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, "baseUrl": ".", "paths": { "@/*": ["./src/*"] }, "jsx": "react-jsx" }, "include": ["src"], "references": [{ "path": "./tsconfig.node.json" }] } -
tsconfig.node.jsonCreate a
tsconfig.node.jsonfile for Vite-specific TypeScript settings:{ "compilerOptions": { "composite": true, "module": "ESNext", "moduleResolution": "bundler", "isolatedModules": true, "esModuleInterop": true, "skipLibCheck": true }, "include": ["vite.config.ts"] }You can read more about these options in the TypeScript documentation.
9. Remove react-env.d.ts and Add vite-env.d.ts
Replace react-env.d.ts with vite-env.d.ts to ensure the correct TypeScript
types are used for Vite.
-
Remove
react-env.d.tsDelete the
react-env.d.tsfile from your project. -
Add
vite-env.d.tsCreate a new file named
vite-env.d.tsin thesrcdirectory with:/// <reference types="vite/client" />
10. Test and Debug
Start the Vite development server to make sure everything is working correctly:
npm run start
11. Build for Production
To build the project for production:
npm run build
This will generate a production-ready build in the build directory, similar
to CRA.
12. Test the Build Output
After building the project for production, serve the build output locally to make sure the app works as expected:
npx serve -s build
