答案是浏览器或服务器缓存及Nginx MIME类型配置错误导致:Network面板显示304或from disk cache,或Content-Type为text/plain而非text/css;需检查Nginx是否包含include mime.types、路径权限、alias斜杠匹配及多层缓存冲突。

为什么改了 CSS 页面还是旧样式?
不是代码没保存,也不是浏览器没刷新——是缓存链上某一层把旧文件钉死了。典型表现:开发者工具 Network 面板里 style.css 状态码是 304 或直接显示 from disk cache,但内容明显是上个版本的;或者更隐蔽地,Content-Type 是 text/plain,浏览器压根不解析。
Nginx 返回 text/plain 而不是 text/css 怎么办?
这是静态资源“加载了但无效”的元凶之一。Nginx 没加载 MIME 类型配置时,默认 fallback 到 default_type text/plain,CSS/JS 就变成纯文本。
- 检查 Nginx 配置中是否包含
include mime.types;(必须在http块顶层,不是server或location内) - OpenResty 或自编译 Nginx 要写绝对路径,比如
include /usr/local/openresty/nginx/conf/mime.types; - 加一句兜底:
default_type text/html;,比default_type application/octet-stream;更安全,至少不会让 CSS 被当二进制丢弃 - 用
curl -I https://yoursite.com/static/style.css看响应头里的Content-Type是否为text/css
文件名没变,但加了 expires 1y 导致用户永远看不到新版本
长缓存策略只有配合内容哈希才真正生效。否则 Nginx 一返回 Cache-Control: max-age=31536000,浏览器就再也不会发请求,哪怕你已替换了服务器上的 app.js。
- Flask/Django 开发阶段可用
url_for('static', filename='app.js?v=' + str(time.time()))强制刷新(仅调试) - 生产环境推荐构建时重命名,如
app.a1b2c3.js,再配 Nginxlocation /static/ { alias /path/to/static_prod/; expires 1y; } - 避免在
location块里混用add_header Cache-Control和expires,二者冲突时以expires为准 - 若用 Gunicorn/Uvicorn 直出静态文件(不推荐),务必禁用其默认缓存头:
static_options={'cache_threshold': 0}(Flask)或手动设置response.headers['Cache-Control'] = 'no-store'
Django/Flask 静态路径映射到 Nginx 后 404
DEBUG=False 后框架不再提供静态文件,全靠 Nginx 直供——但很多人忘了改 alias 或权限,结果所有 /static/css/app.css 全是 404,而 ls /path/to/static_prod/css/ 明明有文件。
立即学习“Python免费学习笔记(深入)”;
- 确认
STATIC_ROOT(Django)或static_folder(Flask)指向的目录真实存在,且 Nginx worker 进程用户(如www-data)有读权限 - Nginx
location /static/ { alias /path/to/static_prod/; }中的斜杠必须对齐:alias路径末尾带斜杠,location也必须带斜杠;若写成alias /path/to/static_prod(无尾斜杠),请求/static/app.css会去找/path/to/static_prodstatic/app.css - 查 Nginx error log,搜
open() "/path/xxx.css" failed (13: Permission denied)——这个比 404 更难发现 - Flask 若已用
send_from_directory处理静态路径,就别让 Nginx 再抢着映射,否则可能因编码或 header 缺失导致中文路径乱码


















