Every React application starts with a scaffold โ a generated project with the correct build tooling, folder structure, and configuration already in place. In the MERN stack, Vite is the standard scaffolding tool for React. It creates a project with a development server that starts in milliseconds, hot module replacement that updates the browser instantly on every save, and a production build pipeline optimised for modern browsers. In this lesson you will scaffold the MERN Blog client, start the development server, and make your first code changes.
Why Vite, Not Create React App?
| Vite | Create React App (CRA) | |
|---|---|---|
| Dev server start | < 1 second | 10โ60 seconds on large projects |
| HMR speed | Instant โ only updates changed module | Full bundle re-compile on changes |
| Build tool | Rollup (production) | Webpack |
| Maintenance | Actively maintained | Deprecated and unmaintained since 2023 |
| Config | vite.config.js โ minimal, flexible | Ejected or react-scripts โ complex |
type="module" script tag. This is why Vite starts so fast: there is no bundling step at startup. In production, Vite uses Rollup to bundle everything into optimised, minified files.npm create vite@latest without a project name to be prompted interactively. For the MERN Blog, run it from inside your monorepo root: npm create vite@latest client -- --template react. The --template react flag selects the React JavaScript template. Use --template react-ts for TypeScript if you prefer typed React development.vite.config.js to forward /api requests to your Express server โ this avoids CORS entirely in development and is already set up in the project structure from Chapter 2.Scaffolding the MERN Blog Client
# Navigate to your monorepo root (mern-blog/)
cd mern-blog
# Scaffold the React client with Vite
npm create vite@latest client -- --template react
# Expected output:
# โ Project name: client
# โ Package name: client
# Scaffolding project in /mern-blog/client...
# Done.
# Install dependencies
cd client
npm install
# Install core packages for the MERN Blog client
npm install axios react-router-dom
# Start the development server
npm run dev
# Expected output:
# VITE v5.x.x ready in 312 ms
# โ Local: http://localhost:5173/
# โ Network: use --host to expose
What Gets Scaffolded
client/
โโโ public/
โ โโโ vite.svg โ static assets served at /
โโโ src/
โ โโโ assets/
โ โ โโโ react.svg โ imported assets (processed by Vite)
โ โโโ App.css โ styles for App component
โ โโโ App.jsx โ root application component
โ โโโ index.css โ global styles
โ โโโ main.jsx โ entry point โ mounts React into the DOM
โโโ index.html โ HTML shell โ Vite injects the JS bundle here
โโโ vite.config.js โ Vite configuration
โโโ package.json
Your First Code Change
// src/App.jsx โ replace the scaffolded content
function App() {
return (
<div className="app">
<header>
<h1>MERN Blog</h1>
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
</nav>
</header>
<main>
<p>Welcome to the MERN Blog. Posts will appear here.</p>
</main>
</div>
);
}
export default App;
Save the file โ Vite detects the change โ HMR updates the browser instantly
No page reload required โ the component updates in place within milliseconds
Configuring the Vite Proxy for the Express API
// client/vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
server: {
port: 5173,
proxy: {
// Forward all /api requests to the Express server during development
'/api': {
target: 'http://localhost:5000',
changeOrigin: true,
},
},
},
});
// With this config:
// fetch('/api/posts') in React โ forwarded to http://localhost:5000/api/posts
// No CORS issues in development โ the proxy makes it same-origin
// In production: deploy React to a CDN and configure CORS on Express
npm Scripts in the React Project
{
"scripts": {
"dev": "vite", // Start dev server at http://localhost:5173
"build": "vite build", // Build for production โ dist/ folder
"preview": "vite preview", // Preview the production build locally
"lint": "eslint . --ext js,jsx"
}
}
Common Mistakes
Mistake 1 โ Running npm install in the wrong directory
โ Wrong โ installing React packages in the server directory:
cd mern-blog/server
npm install axios react-router-dom # wrong directory โ installs in server/node_modules
โ Correct โ always cd into client/ before installing client packages:
cd mern-blog/client
npm install axios react-router-dom # correct โ
Mistake 2 โ Using CRA instead of Vite for new projects
โ Wrong โ starting with the deprecated Create React App:
npx create-react-app client # deprecated โ slow dev server, unmaintained
โ Correct โ always use Vite for new React projects:
npm create vite@latest client -- --template react # โ fast, modern
Mistake 3 โ Forgetting to configure the Vite proxy
โ Wrong โ making API calls with the full URL in development:
fetch('http://localhost:5000/api/posts') // hardcoded dev URL โ breaks in production
โ Correct โ use the Vite proxy and relative URLs:
fetch('/api/posts') // relative URL โ proxied to Express in dev, direct in production โ
Quick Reference
| Task | Command |
|---|---|
| Scaffold React + Vite | npm create vite@latest client -- --template react |
| Install dependencies | cd client && npm install |
| Start dev server | npm run dev |
| Build for production | npm run build |
| Preview production build | npm run preview |
| Dev server port | http://localhost:5173 |