HTTP 缓存详解

HTTP 缓存详解

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

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

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

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

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

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

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

什么是强制缓存?

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

javascript 复制代码
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 缓存,能让你的页面加载速度 "起飞"------ 毕竟少发一次请求,就多省一点时间。

来源:CTO成长日记

相关推荐
源远流长jerry3 小时前
curl、ping、iptables、iperf、tcpdump解析
网络·网络协议·测试工具·ip·tcpdump
@淡 定3 小时前
Redis热点Key独立集群实现方案
数据库·redis·缓存
Arwen3036 小时前
SSL 加密证书助力企业构建安全的网络环境
网络·网络协议·tcp/ip·安全·php·ssl
木鱼布8 小时前
聊聊防火墙技术
网络·网络协议·tcp/ip
longson.9 小时前
怎样避免空间碎片而且高效的分配空间
嵌入式硬件·缓存
不染尘.9 小时前
进程切换和线程调度
linux·数据结构·windows·缓存
xixixi7777710 小时前
CDN(内容分发网络)——缓存和分发网站、应用程序、视频等内容,以提高用户访问速度和稳定性,减少网络延迟和拥塞,同时减轻源服务器的压力
网络·缓存·架构·系统架构·cdn·业务·内容分发网络
ANnianStriver10 小时前
redis安装包方式下载安装
数据库·redis·缓存
liulilittle11 小时前
OPENPPP2 Code Analysis Two
网络·c++·网络协议·信息与通信·通信
lowhot13 小时前
各种网络协议比较
网络·网络协议