Skip to main content
AI
6 min read
February 1, 2026

Using AI to Migrate from CRA to Vite in Hours Instead of Weeks

The CRA Migration Everyone Is Dreading

Segev Sinay

Segev Sinay

Frontend Architect

Share:

The CRA Migration Everyone Is Dreading

Create React App is officially dead. The React team removed it from the docs, it has not received meaningful updates in years, and the build times on any non-trivial project are painful. If you are still on CRA, you know the drill: 30-second cold starts, 10-second hot reloads, and a webpack config you cannot touch without ejecting.

I have migrated five CRA projects to Vite in the last year. The first one took me almost two weeks. The last one took four hours. The difference was using AI assistance strategically at every step.

Here is the exact process I follow now.

Step 1: Analyze Your Current Setup (15 Minutes)

Before touching anything, you need a complete picture of what CRA is doing for you. Use this prompt:

Read package.json and analyze this Create React App project:

1. List every dependency that is CRA-specific or webpack-specific
2. List every environment variable used (grep for REACT_APP_ across the codebase)
3. List every import that uses webpack-specific syntax (require.context, import with
   query params, SVG as React components)
4. Check for proxy configuration in package.json
5. Check for custom configuration via craco, react-app-rewired, or customize-cra
6. List all file types imported (css modules, scss, svg, images, json, etc.)
7. Check if there's a service worker or PWA setup

Give me a migration risk assessment: what will "just work" in Vite,
what needs changes, and what could break.

This analysis is gold. On every project, there are 2-3 things that will break during migration. Knowing them upfront means no surprises later.

Step 2: Create the Vite Configuration (10 Minutes)

Based on the analysis, generate the Vite config:

Based on the analysis of our CRA project, create:

1. vite.config.ts — with these requirements:
   - React plugin with SWC (faster than Babel)
   - Path aliases matching our current tsconfig paths (@/ -> src/)
   - Proxy configuration matching our current package.json proxy
   - SVG handling (we import SVGs as React components)
   - Environment variable prefix change (REACT_APP_ -> VITE_)
   - Build output to 'build' directory (to match current setup)
   - Define any global constants we currently get from webpack

2. index.html — move from public/index.html to root, add the script tag
   for src/main.tsx (Vite requires this)

3. tsconfig changes — update for Vite compatibility

Show me the exact files with complete content.

Here is what a typical Vite config looks like after migration:

// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react-swc';
import svgr from 'vite-plugin-svgr';
import path from 'path';

export default defineConfig({
  plugins: [
    react(),
    svgr(),
  ],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
    },
  },
  server: {
    port: 3000,
    proxy: {
      '/api': {
        target: 'http://localhost:3001',
        changeOrigin: true,
      },
    },
  },
  build: {
    outDir: 'build',
  },
  define: {
    global: 'globalThis',
  },
});

Step 3: Update Environment Variables (10 Minutes)

This is the most tedious part of any CRA-to-Vite migration. Every REACT_APP_ prefix needs to become VITE_, and process.env needs to become import.meta.env.

Search the entire codebase for:
1. Every usage of process.env.REACT_APP_*
2. Every usage of process.env.NODE_ENV
3. Every usage of process.env (any other env vars)

Generate a sed command or codemod that:
- Replaces REACT_APP_ with VITE_ in all source files
- Replaces process.env.REACT_APP_ with import.meta.env.VITE_
- Replaces process.env.NODE_ENV with import.meta.env.MODE
- Updates .env, .env.local, .env.production files with new prefixes

Also update the TypeScript env.d.ts to declare the new VITE_ variables.

Claude Code will generate a script like this:

# Update source files
find src -type f \( -name "*.ts" -o -name "*.tsx" -o -name "*.js" \) -exec sed -i '' \
  -e 's/process\.env\.REACT_APP_/import.meta.env.VITE_/g' \
  -e 's/process\.env\.NODE_ENV/import.meta.env.MODE/g' {} +

# Update env files
for f in .env .env.local .env.development .env.production; do
  [ -f "$f" ] && sed -i '' 's/REACT_APP_/VITE_/g' "$f"
done

Step 4: Handle SVG and Asset Imports (15 Minutes)

CRA lets you do import { ReactComponent as Logo } from './logo.svg'. Vite does not support this out of the box. You need vite-plugin-svgr:

npm install -D vite-plugin-svgr

Then update the import syntax across the codebase:

Find every SVG import in the codebase that uses the CRA pattern:
import { ReactComponent as X } from './something.svg'

Convert each to the Vite + svgr pattern:
import X from './something.svg?react'

Show me every file that needs this change and the exact replacements.

Step 5: Update Package Scripts and Dependencies (10 Minutes)

Update package.json for the CRA to Vite migration:

1. Remove these CRA dependencies: react-scripts, @craco/craco (if present)
2. Add Vite dependencies: vite, @vitejs/plugin-react-swc, vite-plugin-svgr
3. Update scripts:
   - "start" -> "dev": "vite"
   - "build": "vite build"
   - "preview": "vite preview"
   - Remove "eject"
4. Keep all other dependencies unchanged

Show me the exact package.json changes (diff format).

Then install:

npm install

Step 6: Fix Remaining Issues (30-60 Minutes)

Start the dev server and see what breaks:

npm run dev

For each error, give Claude Code the exact error message:

I'm migrating from CRA to Vite and getting this error:

[paste error]

The file causing the issue is src/utils/config.ts.
Our Vite config is [paste vite.config.ts].

What is the cause and what is the exact fix?

Common issues I see on every migration:

  1. Global is not defined — Add define: { global: 'globalThis' } to vite.config.ts
  2. process is not defined — Some libraries reference process.env directly. Fix with the define option.
  3. CSS Modules naming — CRA uses [name].module.css which Vite also supports, but the class name format may differ slightly
  4. Jest configuration — If you use Jest, you need to update the config for Vite. Consider switching to Vitest.
  5. Dynamic imports — Vite uses native ES modules, so require() calls need to become import()

Step 7: Verify and Compare (15 Minutes)

Run the production build and compare:

npm run build

Then use Claude Code to verify:

Compare our CRA build output (in build-cra/) with our new Vite build
output (in build/). Check:

1. Bundle sizes — are they similar or improved?
2. Asset hashing — are assets properly hashed?
3. Source maps — are they generated correctly?
4. index.html — does it reference all chunks correctly?
5. Environment variables — are VITE_ vars properly replaced at build time?

On every migration I have done, the Vite build is 2-5x smaller and 3-10x faster.

Results You Can Expect

Typical improvements I see after migrating:

| Metric | CRA | Vite | Improvement | |--------|-----|------|-------------| | Cold start | 25-45s | 1-3s | 10-15x faster | | Hot reload | 5-15s | <1s | 10-15x faster | | Production build | 60-120s | 10-30s | 4-6x faster | | Bundle size | Baseline | 15-30% smaller | Significant |

The developer experience improvement alone justifies the migration. But the faster CI builds save real money too.

AI
React
Productivity
TypeScript
Technical Leadership
Prompt Engineering
Build Tools
Bundle Optimization

Related Articles

Contact

Let’s Connect

Have a question or an idea? I’d love to hear from you.

Send a Message