强缓存通过cache-control或expires让浏览器直接读本地缓存(200 from cache),协商缓存则依赖etag/last-modified发起条件请求验证,未变返回304;nginx中强缓存需显式配置add_header或expires,协商缓存默认启用且优先使用etag。

在 Nginx 中配置强缓存与协商缓存,核心是通过响应头控制浏览器行为:强缓存靠 Cache-Control 或 Expires 让浏览器跳过请求直接读本地缓存;协商缓存靠 ETag 和 Last-Modified 让浏览器每次发轻量验证请求(If-None-Match/If-Modified-Since),未变则返回 304。
强缓存:用 add_header 或 expires 设置有效期
强缓存适用于长期不变的静态资源,如带哈希名的 JS/CSS、图片、字体等。Nginx 优先使用 Cache-Control(HTTP/1.1),它比 Expires 更可靠(不依赖客户端时间)。
- 推荐写法(显式、可读性强):
add_header Cache-Control "public, max-age=31536000, immutable" always;
其中immutable告诉浏览器该资源在max-age内绝不会变更,连验证请求都不用发。 - 快捷写法(等效但隐含
public):expires 1y;→ 自动设置Cache-Control: max-age=31536000和Expires头 - 注意:
always参数必须加在add_header后,否则 3xx/4xx 响应不会携带该头
协商缓存:默认开启,无需额外配置,但需避免误关
Nginx 对静态文件默认自动提供 ETag 和 Last-Modified 响应头,只要没显式禁用,浏览器就会发起条件请求。这是“开箱即用”的能力。
- 确认启用(默认就是):
etag on;(Nginx 默认值,可省略)if_modified_since exact;(默认行为,精确匹配秒级时间) - 不要手动关闭:
避免写etag off;或add_header Last-Modified "";,否则协商失效,退化为每次全量请求 - 浏览器优先用
ETag验证,Last-Modified是降级兜底——两者共存最稳妥
典型资源分类配置示例
不同资源类型应匹配不同策略,不能一刀切:
-
带内容哈希的静态资源(如
main.a1b2c3.js):location ~* \.[a-f0-9]{8,}\.(js|css|png|jpg|woff2)$ {<br> add_header Cache-Control "public, max-age=31536000, immutable" always;<br>} -
普通静态资源(无哈希,可能小范围更新):
location ~* \.(js|css|png|jpg|gif|svg|ico|woff|woff2)$ {<br> add_header Cache-Control "public, max-age=2592000" always;<br>} -
HTML 入口文件(必须及时更新):
location ~* \.html$ {<br> add_header Cache-Control "private, no-cache, must-revalidate" always;<br>}
→ 禁用强缓存,强制走协商(304),同时禁止 CDN 缓存
验证是否生效的简单方法
打开浏览器开发者工具 → Network 标签页,刷新页面后观察资源响应头和状态码:
- 强缓存命中:状态码显示
200 (from disk cache)或200 (from memory cache),且无网络请求发出 - 协商缓存命中:状态码为
304 Not Modified,响应体为空,但响应头含ETag或Last-Modified - 检查响应头是否存在
Cache-Control、ETag、Last-Modified,是判断配置是否写入成功的直接依据











