server { listen 8080; server_name localhost; root /usr/share/nginx/html; index index.html; # Serve static assets directly (hashed filenames get long cache) location ~* \.(?:js|mjs|css|png|jpg|jpeg|gif|ico|webp|avif|svg|ttf|otf|woff|woff2|map)$ { access_log off; etag on; # If you build with hashed filenames (e.g. app.abc123.js), cache hard: expires 1y; add_header Cache-Control "public, immutable"; try_files $uri =404; } # Never cache index.html so deploys go live immediately location = /index.html { etag on; add_header Cache-Control "no-cache"; } # SPA fallback for client-side routes location / { try_files $uri $uri/ /index.html; } # Basic error page (optional) error_page 500 502 503 504 /50x.html; location = /50x.html { internal; } # Security hardening location ~ /\.ht { deny all; } # Gzip (works fine with your asset types) gzip on; gzip_disable "msie6"; gzip_vary on; gzip_proxied any; gzip_comp_level 6; gzip_buffers 16 8k; gzip_http_version 1.1; gzip_types text/plain text/css text/xml text/javascript application/javascript application/x-javascript application/json application/xml application/xml+rss font/ttf font/otf image/svg+xml; }