Project Setup with Vite
Vite (pronounced "veet", French for "fast") is the recommended way to start a new React project. It replaces Create React App as the de-facto standard because of its dramatically faster development experience, modern architecture, and active maintenance.
Why Vite?
Traditional bundlers like Webpack (used by Create React App) bundle your entire application before serving it to the browser. On a large project this can take 30–60 seconds every time you start the dev server.
Vite takes a different approach. It leverages native ES modules (supported by all modern browsers) to serve source files directly without bundling in development. The browser requests only the files it actually needs, and Vite transforms them on demand using esbuild — a Go-based bundler that is 10–100× faster than JavaScript-based tools.
Instant dev server start — regardless of project size, the server is ready in under a second
Hot Module Replacement (HMR) — when you edit a file, only that module is replaced in the browser. The page does not reload; state is preserved
Optimized production builds — Vite uses Rollup for production bundling with excellent tree-shaking and code splitting
Zero config for most use cases — TypeScript, JSX, CSS Modules, and asset handling work out of the box
Plugin ecosystem — Vite plugins extend functionality (image optimization, SVG imports, PWA support)
Prerequisites
You need Node.js version 18 or higher. Verify your version:
node -v
If the output is below v18, download the latest LTS from nodejs.org.
Step 1: Create the Project
npm create vite@latest my-app -- --template react cd my-app npm install npm run dev
Vite will scaffold the project, then npm install downloads dependencies, and npm run dev starts the dev server. You will see:
VITE v5.x.x ready in 312 ms ➜ Local: http://localhost:5173/ ➜ Network: use --host to expose
Open http://localhost:5173 in your browser. You will see the default Vite + React starter page with a click counter.
Step 2: TypeScript (Recommended)
For new projects, use the TypeScript template:
npm create vite@latest my-app -- --template react-ts cd my-app npm install npm run dev
The TypeScript template adds tsconfig.json, tsconfig.app.json, tsconfig.node.json, and changes all .jsx files to .tsx.
Understanding the Generated Files
After scaffolding, your project looks like this:
my-app/ ├── public/ │ └── vite.svg # static assets served at / ├── src/ │ ├── assets/ │ │ └── react.svg # imported as a module │ ├── App.css # styles for App component │ ├── App.jsx # root App component │ ├── index.css # global styles │ └── main.jsx # entry point — mounts React tree ├── .gitignore ├── eslint.config.js # ESLint configuration ├── index.html # the HTML shell (Vite's entry point) ├── package.json ├── README.md └── vite.config.js # Vite configuration
Key Files Explained
index.html — Unlike CRA (which hides index.html in public/), Vite treats index.html as the application's entry point. It lives at the project root and contains a <script type="module"> tag that imports main.jsx:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<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>src/main.jsx — The React entry point. It creates a React root and renders the App component into the #root div:
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.jsx'
createRoot(document.getElementById('root')).render(
<StrictMode>
<App />
</StrictMode>,
)src/App.jsx — Your root component. Start here. Delete the boilerplate and build your application from this file outward.
vite.config.js — Vite's configuration file. The default React config is minimal:
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
})The @vitejs/plugin-react plugin enables JSX transformation and React Fast Refresh (HMR that preserves component state across edits).
Available Scripts
npm run dev— start the development server at http://localhost:5173npm run build— create an optimized production bundle in thedist/foldernpm run preview— serve the production build locally to test before deployingnpm run lint— run ESLint (if configured)
Adding Common Libraries
Once your project is scaffolded, you will typically add a few more packages:
# Routing npm install react-router-dom # Data fetching & server state npm install @tanstack/react-query # Forms npm install react-hook-form # Styling (Tailwind) npm install -D tailwindcss postcss autoprefixer npx tailwindcss init -p
Configuring Path Aliases
Deep relative imports like ../../../components/Button become hard to read. Add a path alias so you can write @components/Button instead:
// vite.config.js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import path from 'path'
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
'@components': path.resolve(__dirname, 'src/components'),
'@hooks': path.resolve(__dirname, 'src/hooks'),
'@utils': path.resolve(__dirname, 'src/utils'),
},
},
})If you are using TypeScript, also update tsconfig.app.json:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@components/*": ["src/components/*"],
"@hooks/*": ["src/hooks/*"],
"@utils/*": ["src/utils/*"]
}
}
}Deploying a Vite Build
Run npm run build to create a dist/ folder. This folder contains plain HTML, CSS, and optimized JavaScript — it can be deployed to any static host: Vercel, Netlify, GitHub Pages, AWS S3 + CloudFront, or any CDN.
npm run build # dist/ folder is ready to deploy npm run preview # Serves dist/ at http://localhost:4173 — test before deploying