server { listen 80; server_name _; root /usr/share/nginx/html; index index.html; gzip on; gzip_vary on; gzip_min_length 1024; gzip_types text/plain text/css text/xml text/javascript application/javascript application/json application/xml+rss; client_max_body_size 800m; # SPA routing - index.html 禁止缓存,确保每次获取最新版本 location = /index.html { add_header Cache-Control "no-cache, no-store, must-revalidate"; add_header Pragma "no-cache"; expires 0; } # SPA fallback location / { try_files $uri /index.html; # HTML 文档(含 try_files 回退的 SPA 路由,如 /login /app/dashboard)一律 no-cache, # 每次校验 ETag/Last-Modified,保证发版后旧标签页重新加载拿到新 chunk 引用; # 带 hash 的静态资源由下方 ~* \.(js|css...) location 优先匹配,不受影响、保持 immutable add_header Cache-Control "no-cache" always; } # API proxy — Staging 环境代理到 staging API 容器 resolver 127.0.0.11 valid=10s; resolver_timeout 5s; location /api/ { proxy_pass http://xiaoxia-api-staging:8000/api/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 300s; proxy_send_timeout 300s; proxy_request_buffering off; } # Generated files — 通过 alias 映射容器内 /app/generated/ 目录 location /generated-files/ { alias /app/generated/; } # 静态资源长缓存 location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { expires 1y; add_header Cache-Control "public, immutable"; } }