Skip to Content
Module 2: React Fundamentals2.2 React Project Setup (Vite)

Module 2.2: React Project Setup (Vite)

Vite Setup Banner

🎯 Learning Objectives

After completing this lesson, you will be able to:

  • Understand why Vite is chosen over Create React App.
  • Create a React + TypeScript project with Vite.
  • Master the folder structure of a Vite project.
  • 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 React team no longer recommends CRA as of 2023.
  • Slow: Using Webpack, cold setup can take 30-60 seconds for large projects.
  • Difficult to customize: It requires ejecting to change the configuration.
  • 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

Vite vs. Create React App Performance Comparison Chart

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.x

If 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-app

Interactive Selection Steps:

  1. Select a framework: Choose "React" using arrow keys.
  2. Select a variant: Choose "TypeScript".

Explanation:

  • npm create vite@latest: Uses the latest version of the create-vite package.
  • my-react-app: The project folder name.

2.3. Install Dependencies & Run the Dev Server

cd my-react-app npm install npm run dev

Terminal output showing Vite development server starting up

Expected Output:

VITE v5.x.x ready in 300 ms ➜ Local: http://localhost:5173/ ➜ Network: use --host to expose ➜ press h + enter to show help

Open your browser at http://localhost:5173/ to view your app.

Default Vite React app page in browser

2.4. Troubleshooting

Error: npm create isn’t working

# Try with npx npx create-vite@latest my-react-app

Error: Port 5173 is already in use

# Change the port npm run dev -- --port 3000

Error: Permission denied (macOS/Linux)

sudo chown -R $(whoami) ~/.npm

3. 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 configuration

3.2. Key Differences (vs. CRA)

  1. index.html at the root: Vite uses it as the entry point instead of JavaScript.
  2. type="module": The script tag uses ES Modules <script type="module" src="/src/main.tsx">.
  3. vite.config.ts: This is the configuration file, replacing the hidden webpack.config.js.

3.3. public/ vs. src/assets/

FolderProcessingURLUse Case
public/No/filename.pngfavicon, robots.txt
src/assets/Yes (hashed)Imported in codeImages, 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 TypeScript 7.0, baseUrl is deprecated. You only need to use paths with relative paths like ./.

4.3. Vite Configuration

Install @types/node:

npm install -D @types/node

Update 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-prettier

Create 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

ScriptCommandPurpose
devnpm run devRuns the development server (HMR)
buildnpm run buildBuilds to dist/ for deployment
previewnpm run previewTests the production build
lintnpm run lintChecks code for errors
formatnpm run formatFormats code beautifully (Prettier)

7. References

Last updated on