0.2 · difficulty 1/4 · 5 min read
A working Vite project in five minutes
Scaffold a React + TS project with create-vite and learn what every file in the directory means.
Scaffolding
pnpm create vite@latest hello-vite --template react-ts
cd hello-vite
pnpm install
pnpm devOpen http://localhost:5173 and you should see the default Vite welcome page. A few things are worth noticing:
- Cold start took under a second, and we did nothing to optimize Vite
- Edit a string in
src/App.tsxand the browser updates without a refresh (HMR) - The project root has no
webpack.config.js-style monster
Directory anatomy
hello-vite/
├── index.html ← Vite's entry — not a JS file under src
├── vite.config.ts ← config entry
├── package.json
├── tsconfig.json
├── src/
│ ├── main.tsx ← React mount point
│ ├── App.tsx
│ └── vite-env.d.ts ← global types Vite injects
└── public/ ← static assets that bypass the buildThe most counter-intuitive bit: index.html sits at the project root, not under public/. Vite treats index.html as the entry node of the module graph. The line <script type="module" src="/src/main.tsx"> is where Vite finds every source file from.
What one line of config buys you
// vite.config.ts
import { defineConfig } from "vite"
import react from "@vitejs/plugin-react"
export default defineConfig({
plugins: [react()],
})Once @vitejs/plugin-react is installed, you get for free:
- React Fast Refresh (component state preserved during HMR)
- JSX compilation
- automatic JSX runtime support, so most new files do not need
import React from "react"
We'll take this plugin apart later.
What The Four Commands Actually Do
The setup sequence looks like simple scaffolding, but it maps to four different project phases:
| Command | What actually happens |
|---|---|
pnpm create vite@latest | Downloads create-vite and writes the minimal template files |
pnpm install | Installs Vite, the React plugin, React runtime packages, and TypeScript-related dependencies |
pnpm dev | Starts the Vite dev server and serves source through native ESM |
Opening localhost:5173 | The browser requests index.html, then follows module imports into your source files |
When pnpm dev starts quickly, do not assume Vite already compiled the whole project. It prepared the server and dependency cache; source modules are transformed when the browser asks for them.
Verify Three Things Immediately
After the first successful run, do not stop at the welcome page. Run three quick checks:
- Edit React component text: change
src/App.tsxand confirm the page updates without a full reload. - Edit CSS: change
src/App.cssand confirm styles hot-update as well. - Open the Network panel: refresh and observe separate requests for
main.tsx,App.tsx, and other source modules.
These checks correspond to Vite's three basic ideas: on-demand source transform, HMR, and native browser ESM. The rest of the guide keeps returning to them.
Common Startup Problems
Triage common failures in this order:
| Symptom | Check first |
|---|---|
pnpm create vite@latest is slow | npm registry, proxy, company network |
pnpm dev reports a Node version error | Whether Node satisfies the project requirement |
| Port is not 5173 | 5173 is occupied; Vite tries the next available port |
| Page opens but HMR does not work | Browser console, WebSocket connection, proxy setup |
| TypeScript cannot find Vite globals | Whether src/vite-env.d.ts exists |
Do Not Rush Into Configuration
The easiest beginner mistake is to add configuration immediately after creating a project. A better order:
- Understand why
index.htmlis the entry. - Learn what the plugin array in
vite.config.tsdoes. - Learn the separate jobs of
dev,build, andpreview. - Only then add aliases, proxies, build output rules, or other real requirements.
Configuration is not better because it arrives earlier. Vite's defaults are intentionally enough for the first stage of most frontend apps.
What Counts As Actually Working
"A page appears in the browser" is only the first step. A Vite project is really working when:
pnpm devstarts and HMR works for both TSX and CSS.pnpm buildproducesdist/without TypeScript or build errors.pnpm previewcan serve the production output with correct asset paths.- The browser console has no React Refresh preamble, module resolution, or asset 404 errors.
This check order appears again throughout the hands-on projects. Dev working only proves the dev server path. Build and preview passing means the production build and deployment paths are basically sound.
Self-check
- Why is
index.htmlat the project root rather than insidepublic/? - After
pnpm dev, the Network panel shows lots of?t=xxxxxquery strings. What are they? - Without any plugin, can Vite compile
.tsxfiles? Why?