Nginx 静态资源缓存怎么设?Cache-Control、版本文件名与更新验证
给所有页面统一设置很长的缓存时间,可能让登录状态、接口结果或旧版 HTML 被错误保留。静态资源缓存应先按内容用途分类,再决定保留多久。本文以 Ubuntu 24.04 的 Nginx 静态站点为例,讨论浏览器和共享缓存读取响应头的行为。
先分清哪些文件可以被长时间保存
带内容指纹的 CSS、JavaScript、字体等文件适合长缓存,因为内容变化时文件名也会变化。固定名称的图片和入口 HTML 则要结合更新频率设计策略;如果每次仍覆盖 app.js,浏览器没有理由立刻放弃尚未过期的旧文件。
登录页面、用户资料、购物车和管理接口不能照搬公开静态目录的策略。即使 URL 以某种文件扩展名结尾,也可能由应用动态生成。先核对真实路由和权限,再决定是否允许共享缓存,不能只凭后缀推断安全性。
让缓存规则与资源目录对应
假设站点把可公开访问、文件名含指纹的构建产物放在 /assets/,并使用正常静态目录映射,可以在该路径中增加缓存策略:
location /assets/ {
root /srv/site/public;
try_files $uri =404;
add_header Cache-Control "public, max-age=31536000, immutable";
}
这段配置把 /assets/app.hash.js 映射到 /srv/site/public/assets/app.hash.js。一年仅是适合不可变版本文件的示例值,不应复制到普通 HTML 或会原地更新的文件。没有版本化能力时,应改用较短且符合发布节奏的时长。
add_header 的生效状态码和继承关系需要留意,尤其是站点已有安全响应头时。不要同时在应用、Nginx 和 CDN 各加一份互相冲突的 Cache-Control。Nginx 响应头模块说明
HTML 与静态文件采用不同更新节奏
用户先拿到 HTML,再按其中的地址下载资源。因此入口 HTML 如果长期保留旧版本,即使服务器已经上传新脚本,用户仍可能继续请求旧文件。可以让 HTML 更频繁地重新验证,而把有指纹的资源长期保存。
no-cache 表示使用缓存前需要验证,并不等同于禁止保存;no-store 则用于不应存储的响应。具体选择应结合内容敏感性和应用行为,不能把两个值当同义词。MDN HTTP 缓存指南
发布时先上传新资源,再更新引用它们的 HTML,并保留仍可能被旧页面引用的资源一段时间。否则用户拿到旧 HTML,却发现对应脚本已删除,会产生页面空白或功能失效。回滚也需要旧版资源仍然可用。
从真正访问入口检查响应头
在本地终端查看一个实际存在的资源,Windows PowerShell 使用 curl.exe:
curl -I https://example.com/assets/app.hash.js
替换为自己的域名和真实文件。检查 Cache-Control 是否只有一套可解释的策略、状态码是否正确,以及 CDN 是否覆盖了源站设置。在浏览器开发者工具中分别观察首次加载、再次加载和重新验证,不要仅凭页面感觉判断是否命中缓存。
调试时可以临时禁用浏览器缓存以确认源站内容,但最终验收必须恢复正常缓存行为。只在禁用缓存模式下测试成功,不能说明真实访客已经拿到新文件。出现差异时,逐层比较浏览器、CDN 和源站响应。
缓存设置错误后怎样修复
配置修改前保存原文件,语法检查通过后重新加载。若发现敏感路径被纳入缓存,先修正规则并按所用 CDN 的正式机制失效相关对象,同时检查已经发生的影响。浏览器已经保存的长期缓存,通常无法靠服务端改一个响应头立即收回。
对于资源更新失效,更可靠的做法是发布新的文件名并更新引用,而不是不断刷新整个站点缓存。完成修复后记录目录用途、命名策略和旧资源保留时间,使下一次发布能重复验证,而不是再次依赖用户手动清缓存。