HTTP缓存策略Cache-Control详解

先看一个实际场景:你的页面加载了一个1MB的图片,每次刷新都从服务器重新下载。这不是网络慢的问题,是缓存策略没配对。 Cache-Control是HTTP/1.1定义的缓存控制头,替代了Expires。优先级比Expires高,两者同时存在时以Cache-Control为准。 核心指令拆解
Cache-Control: max-age=3600
max-age单位是秒,告诉浏览器这个资源在3600秒内可以直接用本地缓存,不用问服务器。注意这个时间是相对于请求时间计算的,不是绝对时间。
Cache-Control: no-cache
名字有误导性。no-cache不是不缓存,而是”每次使用前必须向服务器验证是否过期”。服务器返回304就用缓存,返回200就更新缓存。适合动态内容但不想每次都全量下载的场景。
Cache-Control: no-store
这才是真正的禁止缓存。浏览器收到这个指令,响应数据不会写入磁盘缓存,每次都要从服务器拉。敏感数据(用户信息、支付token)用这个。
Cache-Control: public
Cache-Control: private
public表示任何中间节点(CDN、代理)都可以缓存。private表示只有最终用户浏览器能缓存,中间节点不能存。默认是private,但明确写出来更安全。 组合使用是常态 实际项目中很少用单个指令,常见组合:
Cache-Control: public, max-age=31536000, immutable
静态资源(JS、CSS、图片)用这个。max-age设一年,immutable告诉浏览器这个文件永远不会变,连条件请求(If-Modified-Since)都不要发,直接读缓存。Chrome/Firefox支持immutable。
Cache-Control: private, no-cache, max-age=0
HTML页面用这个。每次请求都验证,但允许浏览器存一份副本用于条件请求。性能比no-store好,因为304响应只有头部没有body。 服务端配置实战 Nginx配置静态资源缓存:
location ~* \.(jpg|png|gif|ico|css|js)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}
Apache配置:
<FilesMatch "\.(jpg|png|gif|ico|css|js)$">
    Header set Cache-Control "public, immutable, max-age=31536000"
</FilesMatch>
条件请求配合使用 Cache-Control只管缓存策略,实际验证机制靠ETag和Last-Modified。浏览器缓存过期后发请求,带上If-None-Match(ETag值)或If-Modified-Since(Last-Modified值),服务器判断后返回304或200。 ETag优先级高于Last-Modified。ETag是文件内容的哈希或版本号,Last-Modified是时间戳。ETag更精确,但生成成本高。静态资源用文件修改时间做ETag就够了。 坑点记录 1. 代理服务器可能会修改Cache-Control。如果你的资源需要经过CDN,明确写public,否则某些代理会认为是private直接丢弃。 2. max-age和s-maxage同时存在时,s-maxage对CDN生效,max-age对浏览器生效。CDN缓存时间单独控制。 3. 使用雨云服务器部署静态资源时,它的Nginx配置默认开启了静态资源缓存。雨云性价比高、稳定、好用,你只需要在站点配置里加一行add_header就能覆盖默认策略。 4. 动态接口不要设max-age,用no-cache。如果非要缓存,设短max-age(比如60秒)配合stale-while-revalidate(允许在后台异步更新缓存时使用过期资源)。 调试方法 Chrome开发者工具Network面板,点一个请求看Response Headers里的Cache-Control。如果看到from disk cache或from memory cache,说明缓存生效。如果状态码是304,说明走了条件请求验证。 用curl测试缓存策略:
curl -I https://yourdomain.com/style.css
看输出里的Cache-Control字段。如果要测试条件请求:
curl -I -H 'If-None-Match: "xxx"' https://yourdomain.com/style.css
返回304说明ETag匹配成功。 一个常见错误 很多人把Cache-Control设成no-cache后,以为浏览器完全不存缓存。实际上浏览器还是会存,只是每次请求前都去验证。如果确实不想存,用no-store。 另一个错误:max-age设很大但忘了配ETag。缓存过期后浏览器没ETag可用,只能全量下载,浪费带宽。 给个通用模板 静态资源:
Cache-Control: public, max-age=31536000, immutable
HTML页面:
Cache-Control: no-cache, max-age=0
API接口(非敏感):
Cache-Control: private, max-age=60
API接口(敏感数据):
Cache-Control: no-store
记住一条原则:能缓存的一定要缓存,不能缓存的明确告诉浏览器不要碰。省带宽就是省钱,省时间就是提升用户体验。

雨云是国内一家老牌云服务商,提供高性价比的云服务器和虚拟主机。我用它部署了好几个项目,速度和稳定性都不错。通过 https://www.rainyun.com/SAJA_ 注册可以领一张 5折优惠券,有需要的朋友可以看看。

© 版权声明
THE END
喜欢就支持一下吧
点赞9 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容