server { listen 80; server_name _; root /usr/share/nginx/html; index index.html; # Compression gzip on; gzip_comp_level 5; gzip_min_length 256; gzip_proxied any; gzip_vary on; gzip_types application/javascript application/json application/manifest+json application/wasm application/xml font/woff font/woff2 image/svg+xml text/css text/plain; # Vite emits hashed file names under /assets/ — cache hard location /assets/ { access_log off; add_header Cache-Control "public, max-age=31536000, immutable"; try_files $uri =404; } # PWA control surfaces — never cache, so updates propagate location = /sw.js { add_header Cache-Control "no-store"; try_files $uri =404; } location = /registerSW.js { add_header Cache-Control "no-store"; try_files $uri =404; } location = /manifest.webmanifest { add_header Cache-Control "no-store"; types { } default_type application/manifest+json; try_files $uri =404; } # Workbox precache + sourcemap helpers location ~* ^/workbox-.*\.js$ { add_header Cache-Control "public, max-age=31536000, immutable"; try_files $uri =404; } # SPA fallback — every other path serves index.html (no cache) location / { add_header Cache-Control "no-store"; try_files $uri $uri/ /index.html; } }