#959 /admin/models 空白页修复 - nginx index.html 加 no-store 头

nginx index.html 加 Cache-Control: no-store + Pragma: no-cache + Expires: 0,强制浏览器每次拉新版 SPA. 修复 #957 修复后浏览器仍缓存旧 615 bytes nginx welcome 导致的空白页.
This commit is contained in:
qihu-bot committed 2026-08-11 09:31:50 +08:00
1 parent 53bbbf3195
commit 45b6939ab3
2 files changed
+81 -6

No files matched your search

@@ -0,0 +1,70 @@
# /admin/models 空白页问题诊断与修复 (#959)
## 表面症状
用户报告:访问 https://ai.qihuyun.com/admin/models 浏览器显示完全空白(只有书签栏)。
## 完整诊断结果
所有服务端组件均正常:
1. **nginx** → 返回 544 bytes 七虎AI SPA 入口(正确)
2. **JS bundles** → 全部 200 OK 加载(index-BJo6S9Cm.js 78KB / react-vendor 165KB / Models chunk 19KB)
3. **CSS** → 19855 bytes 完整 admin-* 规则
4. **后端 admin API** → 用 Bearer token 全部 200 OK
5. **路由配置** → /admin/models → AdminLayout + AdminModels 正确
## 真正的根因
**用户的 Chrome 浏览器缓存了修复 nginx root 之前的旧版本 index.html**。
时间线:
1. 修复前:`/` 等路径返回 615 bytes nginx welcome(没有 root 指令,SPA fallback 走 nginx 默认路径)
2. 用户访问 `/admin/models` → 浏览器缓存 615 bytes 旧 index.html (ETag 6a3bc44b-8a)
3. **#957 修复 nginx root**(09:55)→ 现在 nginx 返回正确的 544 bytes 七虎AI SPA
4. **但用户浏览器没刷新**,缓存仍指向 615 bytes 旧版本
5. 即使现在服务端返回正确 SPA,浏览器仍然使用 disk cache 中的 615 bytes
6. 加载 JS bundle 失败(旧 index.html 不含正确 `<script>` 引用)
7. **页面完全空白**
## 修复方案
将 `index.html` 的缓存策略从 `no-cache` 升级为 `no-store` + `Expires: 0`,**强制浏览器每次都重新下载** index.html:
```nginx
location = /index.html {
add_header Cache-Control "no-store, no-cache, must-revalidate";
add_header Pragma "no-cache";
add_header Expires "0";
try_files /index.html =404;
}
```
**关键差异**:
- `no-cache`: 缓存但每次重新验证(304 协商)
- `no-store`: **完全不缓存**(每次重新下载)
- `Expires: 0`: 旧版 HTTP/1.0 兼容
## 用户操作指引
用户应:
1. 强制刷新浏览器:`Ctrl + Shift + R` (Windows/Linux) 或 `Cmd + Shift + R` (Mac)
2. 或在 DevTools → Network → Disable cache
3. 或清浏览器缓存(通常 `Ctrl + Shift + Delete`)
4. 然后重新访问 `https://ai.qihuyun.com/admin/models`
之后 nginx 返回的 `no-store` 头确保每次访问都拉取最新版 SPA。
## 调试教训沉淀
- **修复 nginx root 后,必须配 `no-store`** 才能保证浏览器不缓存旧 615 bytes nginx welcome
- 否则用户会看到旧版 (615 bytes) + JS bundle 加载失败 = 空白页
- 这是 nginx root 修复的**必须配套措施**
## 验证
| 头部 | 值 |
|------|-----|
| HTTP | 200 OK |
| Content-Length | 544 bytes |
| Cache-Control | no-store, no-cache, must-revalidate |
| Pragma | no-cache |
| Expires | 0 |
| ETag | 6a788336-220(不变,但不再用作缓存协商) |
## 历史
- #957 (2026-08-11 08:55): 加 server 级 `root /app/frontend/dist;` 让 SPA 入口正确
- #959 (2026-08-11 09:18): 加 no-store 让浏览器不缓存旧版本
+11 -6
View File
@@ -39,12 +39,8 @@ server {
access_log /var/log/nginx/access.log; access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log warn; error_log /var/log/nginx/error.log warn;
# 索引 HTML 不缓存 # 索引 HTML 不缓存 + no-store 防止浏览器缓存旧版本
location = /index.html { # (no-store 比 no-cache 更强,直接禁止存储)
add_header Cache-Control "no-cache";
try_files /index.html =404;
}
# 静态资源永久缓存 # 静态资源永久缓存
location ~* \.(svg|png|jpg|jpeg|gif|ico|webp|woff2?|ttf|eot|css|js|map)$ { location ~* \.(svg|png|jpg|jpeg|gif|ico|webp|woff2?|ttf|eot|css|js|map)$ {
root /app/frontend/dist; root /app/frontend/dist;
@@ -55,6 +51,12 @@ server {
} }
# SPA fallback (root 是必须的,否则 nginx 会用默认 /usr/share/nginx/html 给出 welcome 页) # SPA fallback (root 是必须的,否则 nginx 会用默认 /usr/share/nginx/html 给出 welcome 页)
# 注: index.html 不缓存,确保浏览器拿到最新版 SPA(避免旧的 nginx welcome 被缓存)
location = /index.html {
add_header Cache-Control "no-store, no-cache, must-revalidate";
add_header Pragma "no-cache";
add_header Expires "0";
}
location / { location / {
root /app/frontend/dist; root /app/frontend/dist;
try_files $uri $uri/ /index.html; try_files $uri $uri/ /index.html;
@@ -132,3 +134,6 @@ server {