最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Nginx 中浏览器缓存如何配合 ETag 和 Last-Modified 实现协商缓存验证
时间:2026-08-27 11:29:48 编辑:袖梨 来源:一聚教程网
协商缓存核心是浏览器“先问再用”,Nginx自动基于文件系统生成Last-Modified和(启用etag on后)弱ETag,响应条件请求返回304;两者分工协作:仅If-Modified-Since时比对时间戳,仅If-None-Match时比对ETag,两者俱全则优先校验ETag。
协商缓存的核心是让浏览器“先问再用”:每次请求前,带着上次拿到的标识去服务端验证是否还能继续用本地副本。Nginx 本身不写业务逻辑,但它能自动基于文件系统信息生成 Last-Modified 和(启用后)ETag,并响应条件请求返回 304 Not Modified —— 整个过程无需前端代码干预,全靠响应头和 Nginx 配置配合。
ETag 和 Last-Modified 各自起什么作用
Last-Modified 是资源最后修改时间(精度为秒),由 Nginx 对静态文件自动设置;ETag 是资源唯一标识(如 W/"12345-67890"),默认不开启,需显式配置 etag on 才会基于文件大小和修改时间生成弱 ETag。
两者不是叠加增强,而是分工协作:
- 客户端只发
If-Modified-Since→ Nginx 只比对Last-Modified - 客户端只发
If-None-Match→ Nginx 只比对ETag - 两个请求头都带 → Nginx 优先校验
ETag,命中即返回 304,不再查时间戳
Nginx 配置的关键点
默认行为已支持基础协商缓存,但要稳定生效,建议明确配置以下几项:
- 在
location块中添加etag on;—— 启用 ETag 自动生成(尤其适合构建产物含 hash、或内容可能更新但 mtime 不变的场景) - 保留
if_modified_since exact;(Nginx 默认值),确保时间比对严格精确 - 搭配
add_header Cache-Control "public, max-age=0, must-revalidate";—— 明确告诉浏览器“缓存立即过期,但必须先验证”,从而触发条件请求 - 避免手动用
add_header ETag,否则与etag on冲突;也不建议对纯静态资源(如图片、字体)强行加 ETag,徒增 inode 查询开销
为什么有些请求没走 304?常见原因
协商缓存失效往往不是 Nginx 没配好,而是链路中某个环节打断了验证流程:
- 后端接口未返回
Last-Modified头 → Nginx 的etag on就不会生效(它依赖该头派生 ETag) - 响应中存在
Set-Cookie或Vary: *→ Nginx 默认跳过缓存逻辑,包括协商验证 - 前端设置了
Cache-Control: no-cache但没配must-revalidate→ 浏览器可能忽略验证意图,行为不一致 - JS/CSS 文件名带哈希(如
app.a1b2c3.js)→ 这类资源更适合强缓存(immutable+max-age=31536000),禁用协商缓存反而更高效
怎么确认协商缓存真的在工作
不用猜,直接用命令验证:
- 首次请求:
curl -I https://yoursite.com/static/app.js,检查响应头是否含Last-Modified和/或ETag - 第二次请求:
curl -I -H "If-None-Match: "xxx"" -H "If-Modified-Since: Wed, 21 Oct 2024 07:28:00 GMT" https://yoursite.com/static/app.js,看是否返回304且无Content-Length - 浏览器开发者工具 Network 标签页中,刷新 JS 文件,状态码显示灰色
304、Size 显示from disk cache或from memory cache即表示成功