Build, Preview, and Deploy
Introduction
Vite builds your Vue app into static files in dist/—HTML, JavaScript, CSS, and assets ready for any static host or Nginx. This chapter covers npm run build, environment modes, asset handling, history-mode SPA deployment, and a minimal Nginx config.
Prerequisites
Production Build
npm run buildOutput:
dist/
├── index.html
├── assets/
│ ├── index-a1b2c3.js
│ └── index-d4e5f6.css
└── favicon.icoPreview locally:
npm run previewOpens a static server for dist/—verify before upload.
Code explanation:
- Filenames include content hashes for cache busting
index.htmlreferences hashed assets automatically
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.comimport.meta.env.MODE is development or production.
Only VITE_* variables are exposed to client code—never put secrets in VITE_ vars.
Public vs Assets
| Directory | Behavior |
|---|---|
public/ | Copied to dist/ root as-is (/favicon.ico) |
src/assets/ | Processed, hashed, imported in components |
<img src="@/assets/logo.svg" alt="Logo" /><!-- public/robots.txt → /robots.txt -->
<link rel="icon" href="/favicon.ico" />Code Splitting
Route lazy imports create separate chunks:
component: () => import("../views/ReportsView.vue"),Analyze bundle:
npm run build -- --mode analyze
# or add rollup-plugin-visualizer (optional)Keep heavy libraries out of the main chunk—lazy routes and dynamic imports.
Deploy to Static Hosts
Netlify / Vercel / Cloudflare Pages:
- Build command:
npm run build - Output directory:
dist - Environment: set
VITE_API_URL
SPA fallback (history mode):
| Platform | Setting |
|---|---|
| Netlify | public/_redirects: /* /index.html 200 |
| Vercel | vercel.json rewrites |
| Nginx | try_files below |
Nginx for Vue SPA
Serve dist/ and fallback to index.html:
Code explanation:
try_files— if/dashboardhas no physical file, serveindex.html; Vue Router handles client route- Long cache for hashed
/assets/files
API on another host—configure CORS on backend or proxy:
location /api/ {
proxy_pass http://127.0.0.1:8000/;
proxy_set_header Host $host;
}See What Is Nginx for the full track.
Hash Mode Alternative
If you cannot configure server fallback:
import { createWebHashHistory } from "vue-router";
createRouter({
history: createWebHashHistory(),
routes: [/* ... */],
});URLs look like https://app.com/#/about—works on any static host without try_files.
Base Path Subdirectory
App hosted at https://example.com/app/:
vite.config.ts:
export default defineConfig({
base: "/app/",
});Router:
createWebHistory(import.meta.env.BASE_URL);Build Checklist
-
npm run buildsucceeds;vue-tscpasses -
VITE_API_URLset for production - Test
npm run preview— routes work on refresh - Nginx
try_filesor platform SPA redirect configured - HTTPS via Let's Encrypt or platform TLS
Docker Preview (Concept)
Multi-stage image—build then Nginx serve—details in Vue Docker and CI. Full stack with API: PostgreSQL + Redis deploy pattern.
FAQ
Blank page after deploy?
Wrong base path or assets 404—check browser Network tab.
404 on refresh?
Missing SPA fallback—add try_files or hash history.
env not applied?
Rebuild after changing .env.production; vars are baked at build time.
API URL hardcoded localhost?
Set VITE_API_URL in CI/CD for production builds.
Source maps in production?
build.sourcemap: true optional—hide from public or restrict access.
CDN cache index.html?
Do not long-cache index.html—cache /assets/* only.