JavaScript and React course Β· Module 1: React Basics

Creating a React project with Vite

6 min read
In this lesson6

On a cosmic journey through the React world, you need a suitable ship to set off. In the past, the standard choice was Create React App (CRA), but this tool has been officially deprecated and is no longer maintained. The modern standard for creating React projects is Vite - an ultrafast next-generation bundler.

Ra, our cosmic guide, says: "Abandon the old CRA shuttle - Vite is the new warp drive engine that will take you to the React galaxy faster than ever!"

Why Vite?

Vite (pronounced "veet," from French for "fast") is a modern tool for building frontend applications, created by Evan You (the creator of Vue.js). The React documentation lists it (alongside Parcel and Rsbuild) among the recommended tools when you build an app without a framework.

Why Vite replaced CRA:

  • Lightning-fast server start - Vite leverages native browser ES modules (ESM), so the development server starts in 1-2 seconds (CRA needed 20-40 seconds)
  • Instant Hot Module Replacement (HMR) - code changes appear in the browser in ~50ms, regardless of the application size
  • Modern architecture - built on ESM instead of the older Webpack
  • Fast production builds - since Vite 8 it uses Rolldown (previously Rollup) to bundle files
  • Out-of-the-box support - TypeScript, JSX, CSS Modules, PostCSS work without additional configuration

Creating a new project with Vite

To create a new React project with Vite, open the terminal and type:

1npm create vite@latest my-react-app -- --template react

This command:

  1. Uses npm create to run the Vite generator
  2. vite@latest ensures using the latest version
  3. my-react-app is your project name
  4. --template react selects the React template (also available: react-ts for TypeScript)

After creating the project, navigate to the directory and install dependencies:

1cd my-react-app
2npm install

Then start the development server:

1npm run dev

Your application will be available at http://localhost:5173 in the browser. Note - Vite uses port 5173 by default, not 3000.

Vite + React project structure

After creating the project, you'll see the following structure:

1my-react-app/
2β”œβ”€β”€ node_modules/         # Installed dependencies
3β”œβ”€β”€ public/               # Static files (copied as-is)
4β”‚   β”œβ”€β”€ favicon.svg       # Site icon
5β”‚   └── icons.svg         # Icons
6β”œβ”€β”€ src/                  # Source code
7β”‚   β”œβ”€β”€ assets/           # Assets (images, fonts)
8β”‚   β”‚   └── react.svg     # React logo
9β”‚   β”œβ”€β”€ App.css           # App component styles
10β”‚   β”œβ”€β”€ App.jsx           # Main App component
11β”‚   β”œβ”€β”€ index.css         # Global styles
12β”‚   └── main.jsx          # Application entry point
13β”œβ”€β”€ index.html            # Main HTML file (in root directory!)
14β”œβ”€β”€ vite.config.js        # Vite configuration
15β”œβ”€β”€ package.json          # Project info and dependencies
16β”œβ”€β”€ .gitignore            # Files ignored by Git
17└── .oxlintrc.json        # Linter configuration (Oxlint)

Key differences from CRA

Notice a few important differences:

  • index.html is in the root directory, not in public/ - Vite treats it as the entry point
  • Files use the .jsx extension instead of .js - this clearly signals that a file contains JSX
  • The entry point is main.jsx, not index.js
  • vite.config.js instead of hidden Webpack configuration - you have full control

index.html

In Vite, the index.html file is in the project root directory and looks like this:

1<!DOCTYPE html>
2<html lang="en">
3  <head>
4    <meta charset="UTF-8" />
5    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7    <title>Vite + React</title>
8  </head>
9  <body>
10    <div id="root"></div>
11    <script type="module" src="/src/main.jsx"></script>
12  </body>
13</html>

The key line is <script type="module" src="/src/main.jsx"></script> - Vite loads the application as a native ES module, ensuring a lightning-fast start.

src/main.jsx

This is the React application entry point:

1import React from 'react'
2import ReactDOM from 'react-dom/client'
3import App from './App.jsx'
4import './index.css'
5
6ReactDOM.createRoot(document.getElementById('root')).render(
7  <React.StrictMode>
8    <App />
9  </React.StrictMode>,
10)

This code:

  1. Imports React and ReactDOM
  2. Creates a React "root" in the element with id root
  3. Renders the main App component inside StrictMode

src/App.jsx

The main component of your application:

1import { useState } from 'react'
2import reactLogo from './assets/react.svg'
3import viteLogo from '/vite.svg'
4import './App.css'
5
6function App() {
7  const [count, setCount] = useState(0)
8
9  return (
10    <>
11      <div>
12        <a href="https://vite.dev" target="_blank">
13          <img src={viteLogo} className="logo" alt="Vite logo" />
14        </a>
15        <a href="https://react.dev" target="_blank">
16          <img src={reactLogo} className="logo react" alt="React logo" />
17        </a>
18      </div>
19      <h1>Vite + React</h1>
20      <div className="card">
21        <button onClick={() => setCount(c => c + 1)}>
22          count is {count}
23        </button>
24      </div>
25    </>
26  )
27}
28
29export default App

vite.config.js

The Vite configuration file - simple and readable:

1import { defineConfig } from 'vite'
2import react from '@vitejs/plugin-react'
3
4export default defineConfig({
5  plugins: [react()],
6})

That's all you need! The @vitejs/plugin-react plugin provides JSX support, Fast Refresh (HMR), and other React features.

Available scripts

In the Vite project's package.json you'll find:

  • npm run dev - starts the development server with HMR
  • npm run build - builds the application for production deployment
  • npm run preview - previews the built production version locally
  • npm run lint - checks the code with a linter (in the current template: Oxlint)

Vite vs CRA - comparison

FeatureCRA (deprecated)Vite
StatusDeprecated, no updatesActively maintained
Server start20-40 seconds1-2 seconds
HMR1-3 seconds~50ms
BundlerWebpackRolldown (since Vite 8; previously esbuild + Rollup)
ConfigurationHidden (eject)Explicit (vite.config.js)
ModulesCommonJSNative ES Modules
TypeScriptRequires configurationWorks out-of-the-box

Other tools in the React ecosystem

Besides Vite, it's worth knowing other popular tools:

  • Next.js - a React framework with SSR (Server-Side Rendering), SSG, and file-based routing. Ideal for applications requiring SEO
  • React Router (formerly Remix) - a React framework focused on web fundamentals and progressive enhancement
  • Gatsby - a static site generator with GraphQL

For learning React and building SPA (Single Page Application) applications, Vite is the best choice - fast, simple, and listed in the React documentation.

Ra summarizes: "Vite is the next-generation engine for your React spaceship. Fast startup, instant reactions to course changes, and full control over configuration - everything you need to conquer the galaxy!"

Code for this lesson: App.jsx
1import React, { useState } from 'react';
2
3// Demonstration of Vite + React project structure
4function ViteProjectDemo() {
5  const [activeFile, setActiveFile] = useState('App.jsx');
6
7  const fileStructure = [
8    { name: 'node_modules/', type: 'folder', description: 'Installed packages' },
9    { name: 'public/', type: 'folder', description: 'Static files' },
10    { name: '  vite.svg', type: 'file', description: 'Vite logo' },
11    { name: 'src/', type: 'folder', description: 'Source code' },
12    { name: '  assets/', type: 'folder', description: 'Assets (images, fonts)' },
13    { name: '  App.jsx', type: 'file', description: 'Main component', active: true },
14    { name: '  App.css', type: 'file', description: 'Component styles' },
15    { name: '  main.jsx', type: 'file', description: 'Entry point' },
16    { name: '  index.css', type: 'file', description: 'Global styles' },
17    { name: 'index.html', type: 'file', description: 'Main HTML (in the root directory!)' },
18    { name: 'vite.config.js', type: 'file', description: 'Vite configuration' },
19    { name: 'package.json', type: 'file', description: 'Project configuration' },
20  ];
21
22  const fileContents = {
23    'App.jsx': `import { useState } from 'react'
24import './App.css'
25
26function App() {
27  const [count, setCount] = useState(0)
28
29  return (
30    <>
31      <h1>Vite + React</h1>
32      <div className="card">
33        <button onClick={() => setCount(c => c + 1)}>
34          count is {count}
35        </button>
36      </div>
37    </>
38  )
39}
40
41export default App`,
42    'main.jsx': `import React from 'react'
43import ReactDOM from 'react-dom/client'
44import App from './App.jsx'
45import './index.css'
46
47ReactDOM.createRoot(
48  document.getElementById('root')
49).render(
50  <React.StrictMode>
51    <App />
52  </React.StrictMode>,
53)`,
54    'vite.config.js': `import { defineConfig } from 'vite'
55import react from '@vitejs/plugin-react'
56
57export default defineConfig({
58  plugins: [react()],
59})`,
60    'package.json': `{
61  "name": "my-app",
62  "version": "0.0.0",
63  "type": "module",
64  "scripts": {
65    "dev": "vite",
66    "build": "vite build",
67    "preview": "vite preview"
68  },
69  "dependencies": {
70    "react": "^18.2.0",
71    "react-dom": "^18.2.0"
72  },
73  "devDependencies": {
74    "@vitejs/plugin-react": "^4.2.0",
75    "vite": "^5.0.0"
76  }
77}`
78  };
79
80  return (
81    <div style={{
82      fontFamily: 'Arial, sans-serif',
83      maxWidth: '1000px',
84      margin: '0 auto',
85      padding: '20px'
86    }}>
87      <header style={{
88        background: 'linear-gradient(135deg, #61dafb 0%, #21a1f1 100%)',
89        padding: '30px',
90        borderRadius: '12px',
91        color: 'white',
92        textAlign: 'center',
93        marginBottom: '30px'
94      }}>
95        <h1 style={{ margin: 0, fontSize: '2rem' }}>Vite + React</h1>
96        <p style={{ margin: '10px 0 0 0', opacity: 0.9 }}>
97          Project structure and basic files
98        </p>
99      </header>
100
101      <div style={{
102        backgroundColor: '#1e1e1e',
103        borderRadius: '8px',
104        padding: '20px',
105        marginBottom: '30px',
106        fontFamily: 'monospace'
107      }}>
108        <div style={{ color: '#888', marginBottom: '10px' }}>Terminal:</div>
109        <div style={{ color: '#00ff00' }}>$ npm create vite@latest my-app -- --template react</div>
110        <div style={{ color: '#888', marginTop: '5px' }}>Scaffolding project in /my-app...</div>
111        <div style={{ color: '#00ff00', marginTop: '5px' }}>Done. Now run: cd my-app && npm install && npm run dev</div>
112      </div>
113
114      <div style={{ display: 'grid', gridTemplateColumns: '300px 1fr', gap: '20px' }}>
115        <div style={{
116          backgroundColor: '#252526',
117          borderRadius: '8px',
118          padding: '15px'
119        }}>
120          <h3 style={{ color: '#cccccc', margin: '0 0 15px 0', fontSize: '14px' }}>
121            EXPLORER
122          </h3>
123          {fileStructure.map((item, index) => (
124            <div
125              key={index}
126              onClick={() => item.type === 'file' && setActiveFile(item.name.trim())}
127              style={{
128                padding: '8px 10px',
129                color: item.type === 'folder' ? '#dcb67a' : '#9cdcfe',
130                cursor: item.type === 'file' ? 'pointer' : 'default',
131                backgroundColor: activeFile === item.name.trim() ? '#094771' : 'transparent',
132                borderRadius: '4px',
133                fontSize: '14px',
134                fontFamily: 'monospace'
135              }}
136            >
137              {item.type === 'folder' ? 'β–Έ' : 'β€’'} {item.name}
138            </div>
139          ))}
140        </div>
141
142        <div style={{
143          backgroundColor: '#1e1e1e',
144          borderRadius: '8px',
145          padding: '20px'
146        }}>
147          <div style={{
148            color: '#888',
149            fontSize: '12px',
150            marginBottom: '10px',
151            borderBottom: '1px solid #333',
152            paddingBottom: '10px'
153          }}>
154            {activeFile}
155          </div>
156          <pre style={{
157            color: '#d4d4d4',
158            margin: 0,
159            fontSize: '14px',
160            lineHeight: '1.5',
161            overflow: 'auto'
162          }}>
163            {fileContents[activeFile] || '// Select a file from the list'}
164          </pre>
165        </div>
166      </div>
167
168      <div style={{
169        marginTop: '30px',
170        padding: '20px',
171        backgroundColor: '#fff3e0',
172        borderRadius: '8px'
173      }}>
174        <h3 style={{ color: '#e65100', marginTop: 0 }}>Startup commands</h3>
175        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '15px' }}>
176          <div style={{ backgroundColor: 'white', padding: '15px', borderRadius: '8px' }}>
177            <code style={{ color: '#e65100' }}>npm run dev</code>
178            <p style={{ margin: '5px 0 0 0', fontSize: '14px', color: '#666' }}>
179              Starts the development server
180            </p>
181          </div>
182          <div style={{ backgroundColor: 'white', padding: '15px', borderRadius: '8px' }}>
183            <code style={{ color: '#e65100' }}>npm run build</code>
184            <p style={{ margin: '5px 0 0 0', fontSize: '14px', color: '#666' }}>
185              Builds the production version
186            </p>
187          </div>
188        </div>
189      </div>
190    </div>
191  );
192}
193
194export default function App() {
195  return <ViteProjectDemo />;
196}

Spotted a mistake in this lesson?

Check yourself

Answer the questions from this lesson. Pick an answer to see right away whether it is correct.

  1. 1. What is Vite used for in the React ecosystem?

  2. 2. What is hot reloading in React?

Hands-on tasks in the game

  • Click in order

    Arrange the steps for creating your first React application:

  • Vertical ordering

    Arrange the stages of code transpilation by Babel from top to bottom:

  • Code editor

    Create a simple React App component that displays a heading and a welcome paragraph.

  • Click in order

    Build the command to create a new React project with Vite:

Useful articles