This guide covers the complete deployment process for a Vue.js or React SPA — building, transferring, configuring Nginx with proper routing support, and adding SSL.
Prerequisites
- Node.js installed on your build machine (local or CI)
- Nginx installed on your VPS
Step 1 — Build the Application
For Vite-based projects (both Vue and React commonly use this):
npm install
npm run build
Produces a dist directory with optimized, bundled static files.
Step 2 — Test the Production Build Locally
npm run preview
Verify everything works correctly before deploying — catches issues specific to the production build that might not appear in development mode.
Step 3 — Transfer the Build to Your VPS
rsync -avz --delete ./dist/ deploy@YOUR_SERVER_IP:/var/www/myapp/dist/
Step 4 — Configure Nginx with SPA Routing Support
server {
listen 80;
server_name myapp.example.com;
root /var/www/myapp/dist;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
location ~* \.(js|css|woff2|png|jpg|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
location = /index.html {
add_header Cache-Control "no-cache";
}
}
See How to Configure Nginx for Single Page Applications (SPA Routing) for the reasoning behind this configuration.
Step 5 — Enable the Site and Test
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
Step 6 — Add HTTPS
sudo certbot --nginx -d myapp.example.com
Connecting to a Backend API
If your SPA calls a separate backend API, either configure CORS on the API to allow requests from your SPA's domain, or proxy API requests through the same Nginx server to avoid CORS entirely:
location /api/ {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
}
Environment-Specific Configuration
Build-time environment variables (Vite: VITE_-prefixed, Create React App: REACT_APP_-prefixed) must be set before running npm run build — they're baked into the static output, not read at runtime:
VITE_API_URL=https://api.yourdomain.com npm run build
Setting Up Automated Deployment
See How to Set Up Automatic Static Site Deployment from Git to automate this entire process on every push.
Adding a Loading Splash Screen (Improves Perceived Performance)
Since SPAs typically show a blank page until JavaScript loads and renders, consider adding minimal static loading content directly in index.html that's replaced once the app mounts — improves perceived load time, especially on slower connections.
Common Errors
Blank white page in production, works in development — check the browser console for errors; often caused by an incorrect base path configuration if the app isn't served from the domain root.
404 on refresh for any non-root route — missing the try_files fallback to index.html; see How to Configure Nginx for Single Page Applications (SPA Routing).
Best Practices
- Always test the production build locally before deploying
- Set environment variables before building, not expecting runtime configuration for build-time variables
- Configure proper caching for hashed assets while keeping index.html fresh
Continue Reading
- How to Configure Nginx for Single Page Applications (SPA Routing)
- How to Minify and Bundle Frontend Assets for Production
- How to Set Up Automatic Static Site Deployment from Git
Browse more articles in Static Site Hosting & Frontend Deployment.
