HTTP缓存是一种提升Web性能、减少服务器压力和带宽消耗的关键技术。它的核心思想是“就近存取”,将已请求过的资源副本保存在离用户更近的地方,当再次请求同一资源时,如果条件允许,就直接从本地或中间节点获取,而无需再次访问源服务器。
下面从几个方面来详细介绍HTTP缓存:

一、缓存的好处与位置

好处:

  1. 更快的响应速度:从本地或附近的代理服务器获取资源,延迟远低于访问遥远的源服务器。
  2. 降低服务器负载:大量请求被缓存拦截,源服务器处理请求的压力骤减。
  3. 减少带宽消耗:避免了重复传输相同的资源,节省了网络流量成本。

缓存位置:

  • 浏览器缓存(私有缓存):仅为一个用户服务,存储在其本地浏览器中。这是我们最常接触的缓存。
  • 代理缓存(共享缓存):为多个用户服务,通常部署在公司内网或ISP(网络服务提供商)处,例如CDN就是典型的大型共享缓存系统。

二、缓存的两种核心策略

HTTP缓存主要通过服务器返回的响应头来控制,分为强缓存协商缓存

1. 强缓存

强缓存是指浏览器在缓存未过期的情况下,不向服务器发送请求,直接使用本地缓存。这表现为HTTP状态码200,但在浏览器开发者工具中会看到“from disk cache”或“from memory cache”字样。
控制强缓存的头部字段有:

  • Cache-Control: max-age=<seconds>:这是HTTP/1.1标准,也是目前最高优先级、最常用的字段。它指定一个相对时间,表示资源在多少秒内是新鲜的,可以直接使用。例如Cache-Control: max-age=3600表示资源在接下来的1小时内有效。
  • Expires: <HTTP-date>:这是HTTP/1.0的产物,指定一个绝对过期时间点。由于它依赖于客户端和服务器时间的一致性,存在时钟不同步的风险,因此当与Cache-Control: max-age同时存在时,后者的优先级更高。

2. 协商缓存

当强缓存失效(例如max-age时间已过)时,浏览器会携带资源的缓存标识向服务器发起请求,由服务器判断这个资源是否真的发生了变化。如果没有变化,服务器就返回304 Not Modified状态码,告诉浏览器可以继续使用本地缓存;如果发生了变化,则返回200和新的资源内容。
协商缓存涉及两队头部字段:

  • Last-Modified / If-Modified-Since
    过程:服务器首次响应时,通过Last-Modified头告诉浏览器资源的最后修改时间。浏览器再次请求时,通过If-Modified-Since头把这个时间带回给服务器。服务器比较这个时间与资源的当前最后修改时间,如果一致,则返回304
    缺点:基于时间,精度为秒,如果文件在1秒内发生多次修改,或者文件内容没变但修改时间变了(如单纯覆盖),都会导致判断不准确。
  • ETag / If-None-Match
    过程:ETag是服务器为资源生成的一个唯一标识(通常是哈希值)。浏览器下次请求时,通过If-None-Match头把这个标识带回。服务器比较ETag,如果一致则返回304
    优点:精度更高,可以精确感知文件内容的任何变化。当ETagLast-Modified同时存在时,ETag的优先级更高。

三、重要的Cache-Control指令

除了max-ageCache-Control还有很多其他指令,用于更精细地控制缓存行为:

  • public:表明响应可以被任何对象(包括浏览器、CDN等代理服务器)缓存。
  • private:表明响应只为单个用户服务,只能被浏览器私有缓存,不允许代理服务器缓存。
  • no-cache:注意,这个名字有误导性!它并未“不缓存”,而是指可以缓存,但每次使用前必须向服务器进行协商缓存验证,即强制走协商缓存流程。
  • no-store:这才是真正的“不缓存”。它禁止浏览器和所有中间节点对响应进行任何形式的缓存存储。
  • s-maxage:专门用于共享缓存(如CDN),其优先级高于max-age,仅在public环境下生效。

四、缓存决策流程

浏览器在请求一个资源时,会经历一个清晰的判断流程:

  1. 检查强缓存:判断Cache-Controlmax-ageExpires是否过期。若未过期,直接使用缓存(命中强缓存)。
  2. 进行协商缓存:若强缓存过期,浏览器会携带If-None-Match(对应ETag)或If-Modified-Since(对应Last-Modified)向服务器发起验证请求。
  3. 服务器决策:
    资源未变化:返回304 Not Modified,浏览器继续使用本地缓存。
    资源已变化:返回200 OK及新的资源内容和新的缓存头,浏览器更新缓存。

五、实践中的注意事项

  • 缓存更新:对于频繁变动的资源(如HTML页面),通常设置Cache-Control: no-cache,确保每次都验证。对于长期不变的静态资源(如带哈希的JS、CSS、图片),可以设置一个很长的max-age,例如一年。
  • 浏览器刷新行为:在Chrome浏览器中,普通刷新(F5)会带上协商缓存的请求头;而硬性重新加载(Ctrl + F5 或 Cmd + Shift + R)则会在请求头中加上Cache-Control: no-cachePragma: no-cache,强制跳过所有缓存,向源服务器请求完整资源。

合理利用HTTP缓存,是前端性能优化中最基础也是最有效的一环。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐