浏览器缓存机制

620 阅读4分钟

浏览器的缓存机制对于前端性能优化来说是一个非常重要的环节,浏览器的缓存主要分为两类:强缓存和协商缓存,下面我们将分别介绍下这两种缓存:

强缓存

浏览器在发起http请求时首先检查的就是强缓存,该缓存机制中是不需要发送请求的,主要是通过携带字段确认实现,在早期的http1.0阶段是通过Expires字段,后来的http1.1z中使用Cache-Control字段;

Expires

Expires是指过期时间,它存在服务器的响应头中,用来告诉浏览器在这个过期时间之前是不需要请求的,可以直接使用缓存内容,此时返回304状态码,如果超过过期时间则需要发送请求服务器响应。在这个实现机制中存在一个坑点就是服务器的时间和浏览器的时间可能不一致,这样就会导致过期时间不准确,所以后来的1.1中就抛弃了这个字段,使用了Cache-control字段。

Cache-Control

Cache-Control和Expires最大的区别是它不是采取的过期时间点,而是利用的过期时长,其中通过max-age属性来传达过期时长,如Cache-Control:max-age:3600,此时就表示在一个小时内都可以直接使用缓存内容。其中Cache-Control还有其他的属性,如:

  • public:表示客户端和代理服务器都可以进行缓存
  • private:表示只能客户端缓存
  • no-cache:表示跳过当前的强缓存,发起http请求,直接进入协商缓存
  • no-store:表示不进行缓存
  • s-maxage:表示针对代理服务器的缓存时间

如果在检查中强缓存失效了,则会发起请求,进入到协商缓存。

协商缓存

在强缓存失效后,浏览器会在请求头中携带缓存tag向服务器发起请求,服务器根据该tag值去判断是否使用缓存,其中tag字段分为Last-Modified和Etag

  • Last-modified

    表示最后修改时间,浏览器在向服务器发起请求后,服务器会在响应头中加上该字段,在浏览器下一次发送请求时,会在请求头中携带If-Modified-Since字段,该字段的值就是服务器传来的最后一次修改时间,服务器拿到这个字段值后会和自身的最后修改时间进行对比,如果该字段值小于最后修改时间,则返回304,告诉浏览器使用缓存内容,否则在返回200,新的资源。

  • Etag

    表示服务器根据当前文件资源内容生成的唯一标识,服务器在响应头中将该字段传递给浏览器,浏览器在下次请求时会将这个值作为If-None-match字段的内容并放到请求头中,服务器接收到If-None-Match后会跟服务器上的Etag进行对比,如果两者不一样,说明更新了,返回200,否则返回304,告诉浏览器使用缓存内容。

    两者对比:在精度上Etag是优于Last-modified的,因为Etag是根据资源文件内容生成的唯一标识,因为能准确感知到资源文件内容的变化,而Last-modified是通过时间点来感知,有可能1s内修改多次,此时就不能体现修改。在性能上Last-modified是优于Etag的,Last-Modified仅仅只是记录一个时间点,而 Etag需要根据文件的具体内容生成哈希值。

缓存位置

浏览器的缓存位置共有四种,按照优先级来说分别为:

  • Service Woker
  • Memory Cache
  • Disk Cache
  • Push Cache

Service Worker

它是使Js运行在主线程之外,虽然自己脱离了浏览器,无法访问dom元素,但是它可以实现离线缓存,消息推送等,其中离线缓存就是指Service Woker Cache,同时它也是PWA实现的重要机制。

Memory Cache

它是指内存缓存,它的效率是最快的,但是它的生命周期很短,当渲染进程结束后,它也就不复存在了。

Disk Cache

它是指硬盘缓存,它的存取效率会慢一些,但是它的存储容量和存储时长相对比较有优势。

Push Cache

推送缓存是http2中的内容,目前应用不是恨广泛,后续随着http2的推广,肯定会备受关注的

总结

浏览器在发送请求时,首先会检查强缓存,如果强缓存命中,则不需要发送请求,直接从缓存中获取资源数据,若是强缓存失效,则发送请求进入协商缓存,服务器通过浏览器请求头中Last-Modified和Etag字段进行检查,若是资源更新则返回新的资源数据,200状态码,否则返回304,告诉浏览器使用缓存资源数据即可。