你必须知道的 HTTP 缓存

532 阅读4分钟

前言

HTTP 缓存是一个 web 性能优化的重要手段。HTTP 缓存分为两种,一种是强缓存,另一种是协商缓存。主要作用是加快资源获取速度,提升用户体验,减少网络传输,缓解服务端的压力。

强缓存

强缓存不会向服务器发送请求,直接从缓存中读取资源,在浏览器控制台的 network 选项中可以看到该请求返回 200 状态码。

强缓存可以通过设置 ExpiresCache-Control 两种响应头实现。如果同时存在,Cache-Control 优先级高于 Expires

Expires

Expires 响应头是 HTTP/1.0 的产物。代表该资源的过期时间,其值为一个绝对时间。它告诉浏览器在过期时间之前可以直接从浏览器缓存中存取数据。由于是个绝对时间,客户端与服务端的时间时差或误差等因素可能造成客户端与服务端的时间不一致,将导致缓存命中的误差。

Expires: Thu, 13 Apr 2023 11:35:16 GMT

Cache-Control

Cache-Control 出现于 HTTP/1.1。可以通过指定多个指令来实现缓存机制。主要用表示资源缓存的最大有效时间。即在该时间段内,客户端不需要向服务器发送请求。优先级高于 Expires。其过期时间指令的值是相对时间,它解决了绝对时间的带来的问题。常用的属性值如有:

  • max-age:单位是秒,缓存时间计算的方式是距离发起的时间的秒数,超过间隔的秒数缓存失效。
  • no-cache:在发布缓存副本之前,强制要求缓存把请求提交给原始服务器进行验证 (协商缓存验证)。
  • no-store:缓存不应存储有关客户端请求或服务器响应的任何内容,即不使用任何缓存。
  • private:表明响应只能被单个用户缓存,不能作为共享缓存(即代理服务器不能缓存它)。私有缓存可以缓存响应内容,比如:对应用户的本地浏览器。
  • public:表明响应可以被任何对象(包括:发送请求的客户端,代理服务器,等等)缓存,即使是通常不可缓存的内容。
  • must-revalidate:在缓存过期前可以使用,过期后必须向服务器验证。

协商缓存

协商缓存会先向服务器发送一个请求,服务器会根据这个请求的请求头的一些参数来判断是否命中协商缓存,如果命中,则返回 304 状态码并带上新的响应头通知浏览器从缓存中读取资源。

协商缓存可以通过 Last-Modified/If-Modified-SinceETag/If-None-Match 这两对 Header 来控制。

Last-Modified、If-Modified-Since

Last-Modified 是服务器响应请求时,返回该资源文件在服务器 最后被修改的时间

If-Modified-Since 是客户端再次发起该请求时,携带上次请求返回的 Last-Modified 值,通过此字段值告诉服务器该资源上次请求返回的最后被修改时间。服务器收到该请求,会根据 If-Modified-Since 的字段值与该资源在服务器的最后被修改时间做对比,若服务器的资源最后被修改时间大于 If-Modified-Since 的字段值,则重新返回资源,状态码为 200;否则返回 304,代表资源无更新,可继续使用缓存文件。

ETag、If-None-Match

ETag 是服务器为每份资源生成的唯一标识,资源变化都会导致 ETag 变化,跟最后修改时间没有关系,ETag 可以保证每一个资源是唯一的。

在浏览器发起请求,浏览器的请求头会包含 If-None-Match 字段,其值为上次返回的 ETag 发送给服务器,服务器接收到后发现 If-None-Match 则与被请求资源的唯一标识进行对比。如果相同说明资源没有修改,则返回 304,浏览器直接从缓存中获取数据信息。如果不同则说明资源被改动过,则响应整个资源内容,返回 200。

最后

以上就是笔者对 HTTP 缓存的一些理解,如有不足,欢迎大家在评论区指出~