Build for production with Vite (cheatsheet)
1. Build & optimise with Vite
Always build in production mode
vite buildautomatically setsNODE_ENV=production, bundles with Rollup, tree-shakes and minifies.Split vendor code for long-term caching
Usebuild.rollupOptions.output.manualChunksfrom Rollup to keep dependencies in a separate chunk.Inspect & trim bundle size with
vite-plugin-visualizerorrollup-plugin-visualizer; (if you use latest version of React Router or Tanstack Router, routes are lazy-loaded by default)
2. Handle environment variables
Use Vite’s mode files (
.env.production,.env.staging) and prefix public values withVITE_. vite.devAnything secret belongs on the server or in the deployment platform, never hard-coded into the bundle (it’s baked in at build time). v2.vitejs.dev
CAUTION
Any value stored in Vite environment variables is exposed automatically!.
3. Author a multi-stage Dockerfile
# ---------- build stage ----------
FROM node:24-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --production=false
COPY . .
RUN npm run build # outputs to /app/dist
# ---------- production stage ----------
FROM nginx:1.27-alpine
COPY /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
HEALTHCHECK CMD wget -qO- http://localhost/ || exit 1
USER 1001 # drop root
Include a .dockerignore (node_modules, .git, tests) so build context stays tiny.
4. (if you use it) NGINX runtime tuning
Default config for SPAs:
server { listen 80; root /usr/share/nginx/html; location / { try_files $uri /index.html; } location ~* \.(js|css|ico|png|svg|woff2?)$ { expires 1y; # aggressive static caching access_log off; } location / { try_files $uri /index.html; } location ~* \.(js|css|ico|png|svg|woff2?)$ { expires 1y; # aggressive static caching access_log off; } }Ensures deep links work and static assets are cached heavily.
Add
gzip on; gzip_types text/css application/javascript;(orbrotlimodule) for smaller payloads. medium.com
5. Security & performance extras
Content-Security-Policy headers in NGINX to block inline script injection. dev.to
(additional) Scan the final image with
docker scanor Trivy during CI to catch CVEs. vite.dev
6. CI/CD pattern
Cache
~/.npmor your package manager fodler, and Vite’snode_modules/.vitebetween pipeline runs for faster builds. dev.toUse multi-platform builds (
docker buildx build --platform linux/amd64,linux/arm64) if you target both Intel and ARM servers.Push the image to a registry, then run
docker pull && docker run --rm -d --name web -p 80:80 your/app:tagon the host.
You can start with my simple dockerfiles
7. Verification
Run
docker history your/app:tag—size should be tens of MB, not hundreds.Hit
curl -I localhostinside the container; expect200plus your caching headers.
That's it, hopefully it helps :).