Module 2.2: React Project Setup (Vite)

🎯 Learning Objectives
After completing this lesson, you will be able to:
- Understand why
Viteis chosen over CreateReactApp. - Create a
React+TypeScriptproject with Vite. - Master the folder structure of a
Viteproject. - Configure Path Aliases (
@/components,@/utils). - Set up ESLint + Prettier for
React/TypeScript. - Utilize npm scripts (
dev,build,preview).
1. Why Vite?
1.1. The Problem with Create React App (CRA)
Create React App was once the standard for initializing React projects. However, it faced several challenges:
- ❌ Deprecated: The
Reactteam no longer recommendsCRAas of 2023. - ❌ Slow: Using
Webpack, coldsetupcan take 30-60 seconds for large projects. - ❌ Difficult to customize: It requires
ejectingto change theconfiguration. - ❌ Large bundle sizes: Inefficient code splitting.
1.2. Vite - The Next-Gen Build Tool
Vite uses ESBuild (written in Go) for bundling, making it 10-100 times faster than Webpack (JavaScript).
1.3. Quick Comparison

2. Creating a Project with Vite
2.1. Checking Your Environment
Requirements:
- Node.js >= 18.0.0
- npm >= 9.0.0 or pnpm >= 8.0.0
Check versions:
node -v
# Expected: v18.x.x or v20.x.x
npm -v
# Expected: 9.x.x or 10.x.xIf you haven’t installed Node.js yet: Refer to Module 1.1 or download from nodejs.org .
2.2. Create Your Project
Run the command:
npm create vite@latest my-react-app
# or
pnpm create vite@latest my-react-app
# or
yarn create vite@latest my-react-app
# or
bun create vite@latest my-react-appInteractive Selection Steps:
- Select a framework:
Choose "React"using arrow keys. - Select a variant:
Choose "TypeScript".
Explanation:
npm create vite@latest: Uses the latest version of thecreate-vitepackage.my-react-app: The project folder name.
2.3. Install Dependencies & Run the Dev Server
cd my-react-app
npm install
npm run dev
Expected Output:
VITE v5.x.x ready in 300 ms
➜ Local: http://localhost:5173/
➜ Network: use --host to expose
➜ press h + enter to show helpOpen your browser at http://localhost:5173/ to view your app.

2.4. Troubleshooting
Error: npm create isn’t working
# Try with npx
npx create-vite@latest my-react-appError: Port 5173 is already in use
# Change the port
npm run dev -- --port 3000Error: Permission denied (macOS/Linux)
sudo chown -R $(whoami) ~/.npm3. Folder Structure
3.1. Overview
my-react-app/
├── node_modules/ # Dependencies (do not commit)
├── public/ # Static assets (not processed by Vite)
│ └── vite.svg
├── src/ # Main source code
│ ├── assets/ # Processed assets (images, fonts)
│ │ └── react.svg
│ ├── App.css # Styles for the App component
│ ├── App.tsx # Root component
│ ├── index.css # Global styles
│ ├── main.tsx # Entry point
│ └── vite-env.d.ts # TypeScript declarations for Vite
├── .gitignore # Files to ignore in Git
├── eslint.config.js # ESLint configuration
├── index.html # HTML template (entry point)
├── package.json # Dependencies & scripts
├── tsconfig.json # TypeScript config (for your app)
├── tsconfig.node.json # TypeScript config (for build tools)
└── vite.config.ts # Vite configuration3.2. Key Differences (vs. CRA)
index.htmlat the root:Viteuses it as the entry point instead ofJavaScript.type="module": The script tag usesES Modules<script type="module" src="/src/main.tsx">.vite.config.ts: This is theconfigurationfile, replacing the hiddenwebpack.config.js.
3.3. public/ vs. src/assets/
| Folder | Processing | URL | Use Case |
|---|---|---|---|
public/ | No | /filename.png | favicon, robots.txt |
src/assets/ | Yes (hashed) | Imported in code | Images, fonts |
Example:
// public/logo.png -> Accessed directly
<img src="/logo.png" alt="Logo" />;
// src/assets/react.svg -> Imported
import reactLogo from './assets/react.svg';
<img src={reactLogo} alt="React" />;4. Configuring Path Aliases
4.1. The Problem with Long Imports
// ❌ Long, hard-to-maintain imports
import { Button } from '../../../components/ui/Button';
import { formatDate } from '../../../utils/date';
// ✅ With Path Aliases
import { Button } from '@/components/ui/Button';
import { formatDate } from '@/utils/date';4.2. TypeScript Configuration
Vite’s tsconfig structure:
Vite generates three tsconfig files:
tsconfig.json # Root file, only contains references
tsconfig.app.json # Config for your source code (src/)
tsconfig.node.json # Config for build tools (vite.config.ts)Configure Path Aliases in tsconfig.app.json:
{
"compilerOptions": {
"paths": { "@/*": ["./src/*"] }
// ... other config remains unchanged
}
}⚠️ Note: You must use
"./src/*"(with./), not"src/*". Missing./will result in an error: “Non-relative paths are not allowed when ‘baseUrl’ is not set.”As of
TypeScript7.0,baseUrlis deprecated. You only need to usepathswith relative paths like./.
4.3. Vite Configuration
Install @types/node:
npm install -D @types/nodeUpdate vite.config.ts:
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';
export default defineConfig({
plugins: [react()],
resolve: {
alias: { '@': path.resolve(__dirname, './src') },
},
});4.4. Validation
Open src/App.tsx, delete the default content and replace it with:
// src/App.tsx
function App() {
return <h1>Hello, React + Vite! 🚀</h1>;
}
export default App;Run npm run dev, open your browser at http://localhost:5173/ → Displays “Hello, React + Vite! 🚀” = success!
5. ESLint + Prettier
5.1. Installing Prettier
The Vite template already includes ESLint. We just need to add Prettier.
npm install -D prettier eslint-config-prettier eslint-plugin-prettierCreate the .prettierrc file (Code formatting configuration):
{
"semi": false,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5",
"printWidth": 100,
"bracketSpacing": true,
"jsxSingleQuote": false
}5.2. Integrating with ESLint
Update eslint.config.js for ESLint to recognize Prettier’s rules:
import js from '@eslint/js';
import globals from 'globals';
import reactHooks from 'eslint-plugin-react-hooks';
import reactRefresh from 'eslint-plugin-react-refresh';
import tseslint from 'typescript-eslint';
import prettier from 'eslint-plugin-prettier';
import eslintConfigPrettier from 'eslint-config-prettier';
export default tseslint.config(
{ ignores: ['dist'] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommended, eslintConfigPrettier],
files: ['**/*.{ts,tsx}'],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
plugins: {
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
prettier: prettier,
},
rules: {
...reactHooks.configs.recommended.rules,
'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
'prettier/prettier': 'error',
},
}
);5.3. Adding Scripts & VS Code Configuration
Update package.json:
{
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"preview": "vite preview",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"format": "prettier --write \"src/**/*.{ts,tsx,css,json}\""
}
}Create .vscode/settings.json to enable auto-fixing on save:
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
}
}6. CLI Command Summary
| Script | Command | Purpose |
|---|---|---|
dev | npm run dev | Runs the development server (HMR) |
build | npm run build | Builds to dist/ for deployment |
preview | npm run preview | Tests the production build |
lint | npm run lint | Checks code for errors |
format | npm run format | Formats code beautifully (Prettier) |