Nginx 无 if_modified_since 指令但天然支持 If-Modified-Since 协商缓存,前提是正常发送 Last-Modified 头、禁用干扰的 ETag、确保文件读权限,并结合 expires 实现分层缓存策略。

直接说结论:Nginx 没有名为 if_modified_since 的配置指令,但能天然支持 If-Modified-Since 协商缓存机制——关键在于不干扰、不覆盖、不误禁,让浏览器和 Nginx 共同遵守 HTTP 协议规范。
确保 Last-Modified 头正常发出
这是整个协商缓存生效的前提。Nginx 对静态文件(如 .js、.css、.png)默认基于文件修改时间(mtime)自动添加 Last-Modified 响应头,但容易被意外关闭:
- 检查 location 块中是否写了
add_header Last-Modified ""或unset $sent_http_last_modified—— 这类操作会清空该头,必须删除 - 避免在静态资源路径下启用
etag on;建议显式写etag off;,防止 ETag 与If-None-Match干扰If-Modified-Since的单一逻辑 - 确认 Nginx 进程对文件有读权限,否则无法获取 mtime,
Last-Modified可能为空或返回错误时间
配合 expires 实现“强缓存 + 协商验证”分层策略
只靠 304 不够高效,应优先延长本地缓存周期,把 If-Modified-Since 用在真正需要验证的时机:
- 对内容哈希化资源(如
app.a1b2c3.js),设长缓存:expires 1y;,并加add_header Cache-Control "public, immutable";,彻底跳过验证请求 - 对可能更新的资源(如首页
index.html),设短缓存:expires 10m;,依赖If-Modified-Since在过期后做轻量比对 - 不要给动态接口(如
/api/user)盲目加expires,除非你完全控制内容新鲜度
验证是否真实生效
别只看配置,要用浏览器开发者工具实测:
- 首次请求某个 JS 文件,在 Network 面板查看响应头,确认存在类似
Last-Modified: Wed, 01 Jan 2025 00:00:00 GMT - 等待缓存过期(或手动清空缓存后刷新),观察新请求的请求头是否带
If-Modified-Since,且值与上一次的Last-Modified完全一致 - 若此时文件未改动,Nginx 应返回
304 Not Modified,响应体为空,Size 显示为 “cached” 或 “304”
注意 Windows 环境下的特殊处理
在 Windows 系统部署 Nginx 时,文件系统对 mtime 的精度较低(通常为 1 秒),可能导致高频更新场景下 If-Modified-Since 判断不准:
- 不建议依赖
if_modified_since before类扩展语法(非标准,部分编译版不支持) - 更稳妥的做法是:统一用 Unix/Linux 服务器托管静态资源,或改用
ETag(需后端生成稳定标识)作为补充 - 若必须用 Windows,可配合
open_file_cache提升元数据读取稳定性,减少因文件系统延迟导致的 mtime 获取异常


















