Stop Using Create React App in 2026
·PkgPulse Team
TL;DR
Create React App is dead. It was officially deprecated in 2023 and hasn't received a meaningful update since 2022. Installing it today means 1,200+ packages, Webpack 5 under the hood with 30-60 second build times, and no official support path forward. The React team removed it from their docs. Vite starts in 300ms, builds in under 5 seconds, and comes with first-class TypeScript support. There is no reason to use CRA in 2026.
Key Takeaways
- CRA is officially deprecated — removed from React's official docs in 2023
- 1,200+ transitive dependencies — massive attack surface, slow installs
- Webpack under the hood — 30-60 second builds; Vite builds in 2-5 seconds
- No update path — security vulnerabilities accumulate with no upstream fix
- Vite is the answer — 300ms dev start, 2-5s builds, identical React support
What Happened to Create React App
Timeline:
2016: Facebook releases Create React App
→ Solves "configuration hell" of setting up React + Webpack + Babel
→ Huge success — developers can start in 30 seconds
→ "The blessed way to start React projects"
2018-2020: CRA dominates
→ ~20M weekly downloads at peak
→ Hundreds of tutorials built around it
→ Every bootcamp, every intro course uses CRA
→ Problem: it's accumulating tech debt faster than it's being maintained
2021: Cracks start showing
→ Webpack 5 migration is painful
→ Cold start times: 30+ seconds for medium apps
→ Hot reload: 5-15 seconds per save
→ Other tools (Next.js, Vite) are dramatically faster
→ CRA maintainers are burned out, community contribution drops
2022: CRA development effectively stops
→ Last major release: v5.0.1 (March 2022)
→ Open issues pile up (1,000+)
→ Security vulnerabilities go unpatched
→ The React team starts quietly recommending alternatives
2023: Official deprecation
→ React docs rewritten — CRA removed from recommendations
→ React team announces CRA is in "maintenance mode" (deprecated)
→ Recommended alternatives: Vite, Next.js, Remix
→ npm download count begins multi-year decline
2025-2026: Decline is complete
→ Downloads: still ~500K/week (from legacy CI pipelines and tutorials)
→ But new project starts: near zero
→ Every CRA project is technical debt waiting to be migrated
The Numbers That Killed CRA
# Install time comparison (2026):
# Create React App:
npx create-react-app my-app
# → Downloads: 1,300+ packages
# → Install time: 45-90 seconds (cold cache)
# → node_modules size: ~350MB
# → dev start time: 20-35 seconds
# → Hot reload: 5-15 seconds
# → Production build: 60-120 seconds
# Vite (React template):
npm create vite@latest my-app -- --template react-ts
# → Downloads: ~23 packages
# → Install time: 3-8 seconds
# → node_modules size: ~40MB
# → dev start time: 300ms
# → Hot reload: <100ms (HMR, not full reload)
# → Production build: 2-5 seconds
# Numbers don't lie:
# CRA dev start: 30s vs Vite: 0.3s → Vite is 100x faster to start
# CRA build: 90s vs Vite: 3s → Vite is 30x faster to build
# CRA packages: 1,300 vs Vite: 23 → CRA has 57x more dependencies
# CRA node_modules: 350MB vs Vite: 40MB → CRA takes 9x more disk space
CRA's Core Problem: Webpack
CRA is Webpack all the way down.
Every config decision in CRA was made to abstract away Webpack.
But Webpack's fundamental architecture is blocking:
Webpack (used by CRA):
→ JavaScript-native bundler
→ Processes every file synchronously during module resolution
→ Must scan and process ALL imports before starting dev server
→ 30 second start = 30 seconds of Webpack scanning your 500-file app
→ Hot reload requires rebuilding the affected module graph
Vite (what replaced it):
→ Uses esbuild (Go binary) for dependency pre-bundling
→ Serves files via native ES modules during development
→ Only processes files when the browser actually requests them
→ 300ms start = "I'm ready, request files as you need them"
→ Hot reload replaces only the changed module (no rebuild needed)
The performance difference isn't optimizations.
It's a fundamentally different architecture.
Webpack can't be optimized to match Vite.
The design decisions are incompatible.
What to Use Instead
# Scenario 1: New React SPA (no SSR needed)
npm create vite@latest my-app -- --template react-ts
cd my-app && npm install && npm run dev
# → TypeScript, React Fast Refresh, Vite, ready in under 10 seconds total
# Scenario 2: Next.js app (SSR, file-based routing, API routes)
npx create-next-app@latest my-app
# → Prompts for TypeScript, ESLint, Tailwind, App Router
# → Best choice if you need: SSR, SEO, server components, API routes
# Scenario 3: Full-stack with meta-framework
# Remix
npx create-remix@latest my-app
# → Full-stack, server-centric, data loading patterns
# Tanstack Start
npm create @tanstack/router@latest
# → Type-safe routing, file-based, works with Vite
# Scenario 4: You actually want a static site
npm create astro@latest
# → Build fast static sites, use React for interactive islands
# Decision guide:
# SPA (client-rendered, no SSR) → Vite
# SSR, SEO, server components → Next.js
# Full-stack, form-heavy → Remix
# Static, content-heavy → Astro
# Using CRA → Migrate to Vite
Migrating Existing CRA Projects to Vite
# Migration is surprisingly straightforward
# Step 1: Remove CRA
npm uninstall react-scripts
# Step 2: Install Vite
npm install --save-dev vite @vitejs/plugin-react
# Step 3: Create vite.config.ts
cat > vite.config.ts << 'EOF'
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
server: {
port: 3000, // Match CRA's default port
},
})
EOF
# Step 4: Move index.html
# CRA: public/index.html
# Vite: index.html (root of project)
mv public/index.html .
# Add script tag to new index.html:
# <script type="module" src="/src/main.tsx"></script>
# Step 5: Update package.json scripts
{
"scripts": {
"start": "vite", // was: react-scripts start
"build": "vite build", // was: react-scripts build
"preview": "vite preview", // new: preview production build
"test": "vitest" // replace Jest with Vitest
}
}
# Step 6: Handle environment variables
# CRA: process.env.REACT_APP_*
# Vite: import.meta.env.VITE_*
# → Search and replace: REACT_APP_ → VITE_
# Step 7: Fix absolute imports
# Add to vite.config.ts:
resolve: {
alias: {
'@': '/src',
},
},
# That's the core migration. Most CRA apps migrate in 30-60 minutes.
# Common gotchas:
# → process.env → import.meta.env
# → REACT_APP_ prefix → VITE_ prefix
# → Jest config → Vitest config
# → CRA's built-in ESLint → add your own
The Ecosystem Moved On
Who still uses CRA?
→ Old tutorials on YouTube (pre-2023)
→ Bootcamp courses that haven't updated
→ Legacy enterprise projects from 2019-2022
→ Developers who haven't started a new project since 2022
Who the React ecosystem recommends:
React Docs (react.dev):
→ Next.js ← mentioned first
→ Remix
→ Gatsby (niche)
→ "Vite for SPAs" (effectively)
→ CRA: NOT LISTED
React community consensus (State of JS 2025):
→ Vite: 92% satisfaction rate
→ Next.js: 74% satisfaction
→ CRA: 32% satisfaction (mostly "meh, it used to work")
→ CRA usage intent: negative (more people leaving than joining)
The message is clear:
CRA solved a 2016 problem with 2016 tools.
Vite solved the same problem with 2021 tools.
The performance difference is 10-100x.
There is no reason to use CRA in 2026.
If You're Stuck With CRA (Enterprise Reality)
# You have a 200,000 line CRA app and can't migrate right now.
# What do you do?
# 1. Pin your CRA version
{
"dependencies": {
"react-scripts": "5.0.1" // Last stable version, pin it
}
}
# 2. Override vulnerable transitive dependencies
{
"overrides": {
"semver": ">=7.5.2",
"nth-check": ">=2.0.1",
"postcss": ">=8.4.31"
}
}
# This patches CVEs without needing upstream fixes
# 3. Suppress npm audit noise (CRA will always fail audit)
# .npmrc
# legacy-peer-deps=true
# audit=false ← do NOT do this for security reasons
# Instead: npm audit --audit-level=critical
# Only fail on truly critical vulns, not the hundreds of low/moderate
# 4. Plan the migration
# Migrate one route at a time using module federation or separate Vite apps
# For very large apps: create new routes as Vite micro-frontends
# Run CRA and Vite apps side by side behind a reverse proxy
# 5. Schedule the migration
# CRA is dead weight. It's not a matter of if, but when.
# Every month you wait: more security debt, more friction, slower builds.
# Set a date. Migrate.
Compare Vite vs Webpack (the bundler under CRA) at PkgPulse.
See the live comparison
View vite vs. webpack on PkgPulse →