HTTP 缓存详解

简介: HTTP缓存是提升网页性能的核心机制,通过“强制缓存”和“协商缓存”减少请求、节省带宽。强制缓存由浏览器判断是否过期(如Cache-Control),未过期则直接使用本地资源;过期后进入协商缓存,服务器通过Etag或Last-Modified判定资源是否变更,可复用则返回304。合理配置缓存策略,能显著提升加载速度与用户体验。

HTTP 缓存详解

打开一个网页时,你有没有想过:为什么第二次打开会比第一次快那么多?答案藏在HTTP 缓存里 —— 它是减少网络请求、节省带宽、提升页面加载速度的核心手段。

今天我们就顺着 HTTP 缓存的逻辑,把 “强制缓存”“协商缓存” 这些概念拆透,再补上实际开发里的实用技巧。

一、为什么 HTTP 缓存是性能优化的 “刚需”?

网页里的静态资源(图片、JS、CSS)、甚至部分重复数据,往往是 “重复请求但内容不变” 的。如果每次打开页面都重新从服务器下载这些资源,不仅会拖慢加载速度,还会浪费服务器带宽。

HTTP 缓存的思路很简单:把 “请求 - 响应” 的数据存到本地,下次直接读本地,不用再发网络请求—— 这也是 HTTP/1.1 性能提升的关键设计之一。

而 HTTP 缓存的实现,主要靠 “强制缓存” 和 “协商缓存” 这两层逻辑。

二、第一关:强制缓存 —— 浏览器说了算的 “本地库存”

什么是强制缓存?

就像你家里囤的零食:只要没过期,你就直接拿出来吃,不用再去超市买。强制缓存就是 “浏览器判断缓存没过期,直接用本地存储的资源”,主动权完全在浏览器这边。

Request URL    http://XX.XX.XX.XX:PORT/XXXX/XX/XX.js
Request Method    GET
Status Code    200 OK  (from disk cache)
Remote Address    XX.XX.XX.XX:PORT
Referrer Policy    strict-origin-when-cross-origin

比如上面GET请求响应显示的 “200 (from disk cache)”,就是浏览器直接用了本地磁盘里的缓存资源,连网络请求都没发。

核心控制头部:Cache-Control

强制缓存的 “保质期”,是通过响应头里的Cache-Control字段控制的,它有几个常用指令:

  • max-age=3600:缓存 3600 秒(1 小时)后过期(最常用);
  • public:允许中间缓存(比如 CDN)也存这份资源;
  • private:只有浏览器能存,中间缓存不能存(比如用户专属的资源);
  • no-cache:不是 “不缓存”,是 “需要先协商缓存再用”;
  • no-store:完全不缓存,每次都要从服务器重新请求(比如敏感数据)。

被替代的 “老古董”:Expires

在 HTTP/1.0 里,强制缓存靠Expires字段(比如Expires: Wed, 05 Jan 2026 12:00:00 GMT),它用 “绝对时间” 标记过期时间。

但这个方案有个坑:如果客户端和服务器的时间不同步(比如用户改了本地时间),缓存的过期判断就会出错。所以现在基本用Cache-Control: max-age(相对时间)替代它。

强制缓存的完整流程

  1. 浏览器第一次请求资源,服务器返回资源时,在响应头加Cache-Control: max-age=3600
  2. 浏览器把资源和Cache-Control一起存到本地;
  3. 1 小时内再次请求这个资源:浏览器直接读本地缓存,返回 “200 (from cache)”,不发网络请求;
  4. 1 小时后缓存过期,才会进入下一关 “协商缓存”。

三、第二关:协商缓存 —— 服务器拍板的 “库存核验”

如果强制缓存过期了,是不是就得重新下载资源?不一定 —— 这时候会进入 “协商缓存”:浏览器带着缓存的 “标识” 问服务器 “这个资源过期了,你看看现在能用不?”,服务器判断后决定是用缓存还是发新资源

协商缓存的标志是响应码304 Not Modified—— 意思是 “资源没变化,你用本地缓存就行”。

协商缓存的两种 “标识方案”

服务器和浏览器靠两个头部组合来判断资源是否变化:

方案 1:Last-Modified + If-Modified-Since(基于 “修改时间”)

  • 第一次请求:服务器在响应头加Last-Modified: Wed, 03 Jan 2026 10:00:00 GMT(资源最后修改时间);
  • 缓存过期后请求:浏览器在请求头加If-Modified-Since: Wed, 03 Jan 2026 10:00:00 GMT(把上次的 Last-Modified 带过去);
  • 服务器对比:如果资源现在的修改时间和这个时间一样,返回304;如果不一样,返回200+ 新资源 + 新的 Last-Modified。

方案 2:Etag + If-None-Match(基于 “唯一标识”)

Last-Modified有几个天生的坑:

  • 资源内容没改,但修改时间变了(比如服务器重启),会被误判为 “资源更新”;
  • 时间精度是秒级,如果资源在 1 秒内被多次修改,无法识别;
  • 有些服务器拿不到资源的修改时间。

所以有了更可靠的Etag:服务器给每个资源生成一个唯一标识(比如哈希值),资源内容变了,Etag 就会变。

流程和上面类似:

  • 第一次请求:服务器响应头加Etag: "abc123"
  • 缓存过期后请求:浏览器请求头加If-None-Match: "abc123"
  • 服务器对比:Etag 一样返回304,不一样返回200+ 新资源 + 新 Etag。

优先级:Etag > Last-Modified

如果服务器同时返回了EtagLast-Modified,浏览器会优先用Etag做协商 —— 毕竟它能更准确地判断资源是否真的变化。

四、补充:缓存存在哪?内存 VS 磁盘

浏览器的缓存会存在两个地方:

  • 内存缓存(from memory cache):存在内存里,读取速度极快,但关闭标签页就会被清空(适合小体积、常用的资源,比如 JS/CSS);
  • 磁盘缓存(from disk cache):存在本地磁盘里,读取速度稍慢但持久化(适合大体积资源,比如图片、视频)。

你在浏览器开发者工具里看到的 “from memory cache”“from disk cache”,就是缓存的存储位置标识。

五、开发必看:HTTP 缓存的最佳实践

  1. 静态资源加 “哈希后缀”:比如把app.js改成app.abc123.js—— 资源更新时哈希会变,浏览器会自动请求新资源,不用怕缓存失效不及时;
  2. 合理设置max-age:静态资源(图片、JS/CSS)设长一点(比如max-age=31536000,即 1 年),因为哈希变了会自动更新;
  3. 动态接口用no-cache:比如用户信息接口,加Cache-Control: no-cache—— 强制走协商缓存,既利用缓存又保证数据新鲜;
  4. 配合 CDN 缓存:把静态资源放到 CDN 上,CDN 会帮你缓存资源,进一步减少源站压力。

总结

HTTP 缓存的核心逻辑是 “强制缓存优先,协商缓存兜底”:

  • 强制缓存没过期:浏览器直接用本地资源,零请求成本;
  • 强制缓存过期:通过协商缓存让服务器判断,能复用就返回 304,不能复用再发新资源。

合理利用 HTTP 缓存,能让你的页面加载速度 “起飞”—— 毕竟少发一次请求,就多省一点时间。

目录
相关文章
|
JavaScript 前端开发 索引
问js的forEach和map的区别
JavaScript中的`forEach`和`map`都是数组迭代方法。`forEach`遍历数组但不修改原数组,无返回值;它接受回调函数处理元素。`map`则遍历数组并返回新数组,新数组元素为回调函数处理后的结果。两者都接收元素、索引和数组作为回调函数参数。
285 7
|
消息中间件 Java 开发者
【颠覆想象】Spring Boot重构未来:解耦与隔离,打造坚不可摧的微服务帝国!
【8月更文挑战第29天】本文通过构建电子商务平台的具体案例,深入探讨了如何利用 Spring Boot 实现服务间的解耦与隔离。文章详细介绍了依赖注入、模块化设计及异步通信等关键技术,并提供了具体代码示例。通过依赖注入,对象间耦合得以降低;模块化设计使各功能域独立,降低系统复杂度;异步通信则利用消息队列提升系统吞吐量与响应速度。这些方法不仅优化了系统架构,还加快了开发进程。
341 0
【IDEA用法】IDEA新建文件自动加入SVN,删除文件自动从SVN中删除
【IDEA用法】IDEA新建文件自动加入SVN,删除文件自动从SVN中删除
871 0
|
Linux 网络安全
CentOS 7 SSH连接超时自动断开解决方案
CentOS 7 SSH连接超时自动断开解决方案
1535 0
CentOS 7 SSH连接超时自动断开解决方案
|
弹性计算 运维 安全
阿里云服务器2核2G99元一年,续费同享99元方法介绍(新手用户参考)
阿里云经济型e实例2核2G 3M固定带宽 40G ESSD Entry云盘,价格为99元一年,另外续费也享99元的优惠价格,最多可99元一年续费3次,本文为大家介绍具体续费流程及注意事项。
阿里云服务器2核2G99元一年,续费同享99元方法介绍(新手用户参考)
|
Web App开发 编解码 JavaScript
让Chrome支持小于12px的文字方式
【10月更文挑战第24天】不同的方式可能适用于不同的场景和需求,在实际应用中需要根据具体情况进行选择和权衡。同时,也要密切关注不同浏览器对这些方式的支持情况和可能出现的兼容性问题,以确保文字在各种环境下都能得到良好的显示。
|
消息中间件 存储 缓存
QPS多少,才算高并发 ?
本文详解高并发概念及 QPS 标准,大厂面试高频点,建议掌握收藏。关注【mikechen的互联网架构】,10年+BAT架构经验分享。
QPS多少,才算高并发 ?
|
JavaScript
js【详解】深拷贝 (含 JSON.parse(JSON.stringify(obj)) 的缺陷,5种手写深拷贝)
js【详解】深拷贝 (含 JSON.parse(JSON.stringify(obj)) 的缺陷,5种手写深拷贝)
729 0
|
Java
java -jar 命令隐藏黑窗口
java -jar 命令隐藏黑窗口
599 0
|
Java 开发者 Spring
Spring Boot大法好:解耦、隔离、异步,让代码‘活’起来,性能飙升的秘密武器!
【8月更文挑战第29天】解耦、隔离与异步是Spring Boot中的关键设计原则,能大幅提升软件的可维护性、扩展性和性能。本文通过示例代码详细探讨了这些原则的应用:依赖注入和面向接口编程实现解耦;模块化设计与配置文件实现隔离;`@Async`注解和`CompletableFuture`实现异步处理。综合运用这些原则,可以显著提升软件质量和性能,使系统更加健壮、灵活和高效。
268 0