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

bash
npm run build

Output:

text
dist/
├── index.html
├── assets/
│   ├── index-a1b2c3.js
│   └── index-d4e5f6.css
└── favicon.ico

Preview locally:

bash
npm run preview

Opens a static server for dist/—verify before upload.

Code explanation:

  • Filenames include content hashes for cache busting
  • index.html references hashed assets automatically

Environment Modes

FileLoaded when
.envAll modes
.env.developmentnpm run dev
.env.productionnpm run build

.env.production:

env
VITE_API_URL=https://api.example.com

import.meta.env.MODE is development or production.

Only VITE_* variables are exposed to client code—never put secrets in VITE_ vars.

Public vs Assets

DirectoryBehavior
public/Copied to dist/ root as-is (/favicon.ico)
src/assets/Processed, hashed, imported in components
vue
<img src="@/assets/logo.svg" alt="Logo" />
html
<!-- public/robots.txt → /robots.txt -->
<link rel="icon" href="/favicon.ico" />

Code Splitting

Route lazy imports create separate chunks:

typescript
component: () => import("../views/ReportsView.vue"),

Analyze bundle:

bash
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):

PlatformSetting
Netlifypublic/_redirects: /* /index.html 200
Vercelvercel.json rewrites
Nginxtry_files below

Nginx for Vue SPA

Serve dist/ and fallback to index.html:

Code explanation:

  • try_files — if /dashboard has no physical file, serve index.html; Vue Router handles client route
  • Long cache for hashed /assets/ files

API on another host—configure CORS on backend or proxy:

nginx
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:

typescript
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:

typescript
export default defineConfig({
  base: "/app/",
});

Router:

typescript
createWebHistory(import.meta.env.BASE_URL);

Build Checklist

  • npm run build succeeds; vue-tsc passes
  • VITE_API_URL set for production
  • Test npm run preview — routes work on refresh
  • Nginx try_files or 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.