Files
xiaoxia-saas/infra/docker/nginx.conf
T
xiaoxia f066a8ef4e
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 1s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 1s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 30s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 32s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m13s
AI Code Review / AI Code Review (pull_request) Successful in 1m33s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 1m36s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 1m50s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 2m17s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m2s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 5m4s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 8m58s
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 4s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 6m33s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 8s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 18s
CI/CD Pipeline / Canary Release to Production (pull_request) Failing after 241h19m16s
CI/CD Pipeline / Build Production Web Image (pull_request) Failing after 241h19m19s
CI/CD Pipeline / Deploy Production (pull_request) Failing after 241h19m16s
CI/CD Pipeline / Build Production API Image (pull_request) Failing after 241h19m19s
CI/CD Pipeline / ACR Image Cleanup (pull_request) Failing after 241h27m54s
CI/CD Pipeline / Staging E2E Tests (pull_request) Failing after 241h27m55s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Failing after 241h28m0s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Failing after 241h28m7s
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Failing after 241h28m6s
CI/CD Pipeline / Build Staging Worker Image (pull_request) Failing after 241h28m13s
CI/CD Pipeline / Build Staging API Image (pull_request) Failing after 241h28m16s
CI/CD Pipeline / PR Build Web Image (pull_request) Failing after 241h28m16s
CI/CD Pipeline / Check push changed paths (pull_request) Failing after 241h28m23s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Failing after 241h28m17s
CI/CD Pipeline / Build Production Worker Image (pull_request) Failing after 241h53m55s
CI/CD Pipeline / Staging API Integration Tests (pull_request) Failing after 242h2m30s
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Failing after 242h2m43s
CI/CD Pipeline / Build Staging Web Image (pull_request) Failing after 242h2m51s
CI/CD Pipeline / Frontend Lint (pull_request) Failing after 242h2m53s
fix: SPA 路由回退的 HTML 补 no-cache 头,修发版后旧标签页白屏
问题排查发现两层缺陷:
1. 运行时 bind mount 的 nginx 配置是服务器旧版(无 index.html no-cache 块);
2. 即使最新仓库配置,location = /index.html 只对直接访问 /index.html 生效,
   用户从 /login、/app/dashboard 等路由进入时走 location / 的 try_files 回退,
   返回的 HTML 没有 no-cache 头——旧标签页会长期缓存含旧 chunk 引用的 HTML,
   发版后点菜单就 Failed to fetch dynamically imported module 白屏。

修复:在 location / 块直接 add_header Cache-Control no-cache:
- try_files 回退的 SPA HTML 与 HTML 文档每次校验,发版后能拿到新 chunk 引用
- 带 hash 的静态资源由更高优先级的 location ~* \.(js|css...) 匹配,
  保持 expires 1y + immutable,不受影响

5 份配置同步:infra/docker/nginx{,-staging,-production}.conf +
deploy/configs/nginx{,-staging,-production}.conf(保持一致,避免再混用)
2026-09-06 13:55:40 +08:00

69 lines
2.5 KiB
Nginx Configuration File
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ===========================================
# 小虾剪辑 SaaS — Nginx 配置 (Production 默认)
# ===========================================
#
# 环境隔离说明:
# - staging 使用 nginx-staging.conf → proxy_pass → xiaoxia-api-staging:8000
# - production 使用此文件 → proxy_pass → xiaoxia-api-production:8000
# - 构建时通过 ARG NGINX_CONF 选择配置文件
#
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
# Gzip compression
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 - all routes to index.html
# 注意:不能加 $uri/,否则 /assets 等与构建产物目录同名的路由会被当成目录访问,返回 403
# index.html must never be cached — it contains chunk references
location = /index.html {
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
expires 0;
}
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
# Production environment: proxy to production API container on isolated network
# Use static container name to avoid URI stripping issues with variable-based proxy_pass
resolver 127.0.0.11 valid=10s;
resolver_timeout 5s;
location /api/ {
proxy_pass http://xiaoxia-api-production: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 proxy
location /generated-files/ {
alias /app/generated/;
}
# Cache static assets
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}