这里我们说的缓存主要是指HTTP请求得到的静态资源(img/css/js),使用HTTP缓存的好处是可以减少请求时间,节省带宽流量,减少服务器压力并且提升用户体验,当然并没有绝对完美的东西,HTTP缓存也存在他的缺陷,可能会造成数据不一致,占用内存等

我们将缓存分为强缓存和协商缓存,两者的主要区别是使用本地缓存的时候,是否需要向服务器验证本地缓存是否依旧有效。顾名思义,协商缓存,就是需要和服务器进行协商,最终确定是否使用本地缓存。

这是缓存运作的一个整体流程图:图片来自HTTP缓存

图1

强缓存

强缓存主要有两种Cache-Control和Expires

Cache-Control

Cache-Control是在http1.1中出现的,,Cache-Control有如设置:

  • max-age:它是一个相对时间,表示缓存的有效时间
  • no-cache:不使用本地缓存。需要使用缓存协商,先与服务器确认返回的响应是否被更改,如果之前的响应中存在ETag,那么请求的时候会与服务端验证,如果资源未被更改,则可以避免重新下载。
  • no-store:直接禁止游览器缓存数据,每次用户请求该资源,都会向服务器发送一个请求,每次都会下载完整的资源。
  • public:可以被所有的用户缓存,包括终端用户和CDN等中间代理服务器。
  • private:只能被终端用户的浏览器缓存,不允许CDN等中继缓存服务器对其缓存。

Expires

Expires是http1.0的规范,它的值是一个绝对时间的GMT格式的时间字符串。这个时间代表这这个资源的失效时间,只要发送请求时间是在Expires之前,那么本地缓存始终有效,则在缓存中读取数据。

cache-control:max-age=3600
expires:Fri Apr 02 2021 13:52:41 GMT

Cache-Control与Expires可以在服务端配置同时启用,同时启用的时候Cache-Control优先级高。上面这段配置中,就会按照max-age来使用缓存

协商缓存

ETag/If-None-Match

ETag/If-None-Match 的值是一串 hash 码,代表的是一个资源的标识符,当服务端的文件变化的时候,它的 hash码会随之改变,通过请求头中的 If-None-Match 和当前文件的 hash 值进行比较,如果相等则表示命中协商缓存。ETag 又有强弱校验之分,如果 hash 码是以 “W/“ 开头的一串字符串,说明此时协商缓存的校验是弱校验的,只有服务器上的文件差异(根据 ETag 计算方式来决定)达到能够触发 hash 值后缀变化的时候,才会真正地请求资源,否则返回 304 并加载浏览器缓存。

Last-Modified/If-Modified-Since

Last-Modified/If-Modified-Since 的值代表的是文件的最后修改时间,第一次请求服务端会把资源的最后修改时间放到 Last-Modified 响应头中,第二次发起请求的时候,请求头会带上上一次响应头中的 Last-Modified 的时间,并放到 If-Modified-Since 请求头属性中,服务端根据文件最后一次修改时间和 If-Modified-Since 的值进行比较,如果相等,返回 304 ,并加载浏览器缓存。

ETag作用

Last-Modified与ETag是可以一起使用的,服务器会优先验证ETag,一致的情况下,才会继续比对Last-Modified,最后才决定是否返回304。


前端小白