Nginx中expires max并非真正永久缓存,而是将Expires设为2037年12月31日、Cache-Control设为max-age=315360000(10年),需配合资源路径带哈希等版本标识才能安全生效。

在 Nginx 中配置 expires max 并不能真正实现“永久”缓存,但它会设置一个非常远的过期时间(通常是 2037 年或 9999 年),让浏览器在绝大多数实际场景中将其视为“长期有效”。关键在于:强缓存是否生效,不仅取决于 Expires 或 Cache-Control: max-age,还依赖于资源 URL 是否稳定(即内容变更时 URL 必须变化)。
理解 expires max 的真实含义
expires max 是 Nginx 的快捷写法,等价于:expires 2592000s;(30 天)或更常见的是内部设为 Thu, 31 Dec 2037 23:55:55 GMT(具体值取决于 Nginx 版本)。它不会真的“永久”,但足够长,足以覆盖用户常规访问周期。浏览器收到该响应头后,只要未过期、URL 未变,就会直接从本地磁盘/内存缓存加载资源,不发请求(即强缓存命中)。
必须配合资源指纹(hash)或版本号
如果 HTML 引用的 JS/CSS 文件内容更新了,但文件名没变(比如还是 app.js),而缓存又设为 max,用户将无法获取新版本——这是强缓存最典型的陷阱。
- 正确做法:构建时生成带哈希的文件名,如
app.a1b2c3.js,HTML 中引用该唯一 URL - 或使用查询参数方式(不推荐):
app.js?v=1.2.3,但部分代理和 CDN 可能忽略 query string 缓存 - 确保静态资源路径稳定且内容变更必触发 URL 变化,否则
expires max会锁死旧版本
Nginx 配置示例(针对常见静态类型)
在 server 或 location 块中添加:
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires max;
add_header Cache-Control "public, immutable";
}说明:
-
expires max设置过期时间(同时自动设置Expires和Cache-Control: max-age=...) -
Cache-Control: public允许中间代理缓存;immutable是关键——告诉浏览器该资源在生命周期内不会改变,可跳过条件请求(如If-None-Match),进一步提升复用率(Chrome 49+、Firefox 49+ 支持) - 正则匹配要覆盖所有需强缓存的静态后缀,注意顺序:放在更通用的
location /之前,避免被覆盖
验证与调试要点
打开 Chrome DevTools → Network 标签页,刷新页面后查看静态资源的响应头:
- 确认存在
Cache-Control: public, immutable, max-age=31536000(或类似大数值) - 确认有
Expires字段,时间远在将来 - 首次加载状态码为
200;再次刷新应显示200 (from memory cache)或200 (from disk cache),而非304 - 修改资源内容并重新部署后,检查新 URL 是否被加载,旧 URL 是否仍缓存——这是验证指纹机制是否起效的关键
不复杂但容易忽略:强缓存靠的是“URL 不变 + 过期时间长”,而不是单靠一行配置。只要 URL 稳定、服务端头正确、客户端支持 immutable,就能高效复用静态资源。


















