Build, Preview, and Deploy
Introduction
Vite builds your React app into static files in dist/—HTML, JavaScript, CSS, and assets ready for Netlify, Vercel, OSS, or Nginx. This chapter covers npm run build, environment modes, assets, history-mode SPA deployment, and API/CORS in production.
Prerequisites
Production Build
npm run buildOutput:
dist/
├── index.html
├── assets/
│ ├── index-a1b2c3.js
│ └── index-d4e5f6.css
└── vite.svgPreview locally:
npm run previewVerify routes like /posts/demo work before upload—preview serves dist/ with SPA fallback behavior similar to production hosts.
Code explanation:
- Hashed filenames enable long-term caching
index.htmlreferences hashed assets automatically
Parallel guide: Vue Build and Deploy.
Environment Modes
| File | Loaded when |
|---|---|
.env | All modes |
.env.development | npm run dev |
.env.production | npm run build |
.env.production:
VITE_API_URL=https://api.example.comOr use relative /api with Nginx proxy—no CORS in browser.
const apiUrl = import.meta.env.VITE_API_URL ?? "";
const isProd = import.meta.env.PROD;Only VITE_* variables are exposed—never put secrets in client env vars.
Public vs Assets
| Directory | Behavior |
|---|---|
public/ | Copied to dist/ root (/favicon.ico) |
src/assets/ | Imported in components; hashed in build |
import logo from "./assets/logo.svg";
<img src={logo} alt="Logo" /><link rel="icon" href="/favicon.ico" />Code Splitting
Lazy routes create separate chunks:
const Dashboard = lazy(() => import("./pages/DashboardPage"));Inspect dist/assets/ after build—each lazy page adds a chunk.
Deploy Static SPA
Netlify / Vercel
Connect Git repo; build command npm run build; publish directory dist.
Add redirect for client-side routing:
/* /index.html 200(Netlify _redirects or Vercel vercel.json)
Nginx
try_files fixes 404 on refresh for /dashboard paths.
Full Nginx track: What Is Nginx.
API in Production
| Setup | Config |
|---|---|
| Same domain Nginx proxy | VITE_API_URL= empty; fetch /api/... |
| Separate API subdomain | Backend CORS + VITE_API_URL=https://api.example.com |
| Static CDN + API | CORS on API; restrict origins |
Base Path (Subfolder Deploy)
App at https://example.com/app/:
vite.config.ts:
export default defineConfig({
base: "/app/",
plugins: [react()],
});Router:
createBrowserRouter(routes, { basename: "/app" });Build Checklist
-
npm run buildsucceeds -
npm run preview— home and deep links work - Production
VITE_API_URLor proxy configured - No secrets in
VITE_*vars - Favicon and
public/assets present
Docker multi-stage build: React Docker and CI.
FAQ
Blank page after deploy?
Wrong base path or assets 404—check browser Network tab.
Old bundle cached?
Hashed assets cache safely; index.html should not be cached aggressively during deploys.
Source maps?
Default in build—disable for public repos if concerned: build.sourcemap: false.
Environment per staging?
.env.staging + vite build --mode staging.