• 浏览器缓存机制深入理解与实践(一)


      我们在web开发中常常会遇到这样的场景,有一些较大和常用的资源(例如图片、文档、js、css),在页面打开初始化的时候并不需要用到,而是在用户与页面互动操作触发了某些条件时才需要这些资源(例如我们打开微博可能并不是为了看热搜,但大多数时候我们会点进热搜查看热搜新闻)。

      那么问题来了,如果用户去点击查看热搜时,我们才去加载热搜所需要的相应的资源数据,就显得很被动了。因为在最常用的功能中,来耗费时间等待,这对用户来说其实并不是一个非常好的体验。所以,我们首先想到的是提前将这部分资源加载到浏览器缓存中,本文主要介绍了http两个不同的缓存机制。

    一、http1.0——使用Expires,Last-Modified

      强制缓存:在http1.0时代,当客户端根据地址去获取图片、文档等缓存资源时,我们通过设置响应头中的Expires字段来给定一个时间点,并与放在响应体中的请求资源一同返回给客户端浏览器,并一起被保存于缓存中,下次我们再请求同一个路径地址拿资源时,浏览器强制请求从缓存中获取并返回200状态码。当浏览器的本地时间超过Expires字段设置的时间,缓存资源失效,再请求这个路径时需要去服务端重新获取资源。

      协商缓存:对于一些可能变化较大的资源,我们需要他们及时作出更新,但是又想继续使用缓存这种高效的方式,此时我们便不再使用Expires,而是使用Last-Modified字段,用来记录一个资源的最后改动时间,同样将该字段连同资源一起发返回给客户端。浏览器第二次请求该路径时,顺带把该字段值放入请求头中,不过此时会换一个字段名,变成If-Modified-Since,若服务器的资源发生变化,那这个资源文件肯定会有一个新的变化修改时间,服务器将新时间与旧时间一对比,发现不一致,将新资源放到响应体,新时间放入响应头,返回给客户端,客户端对缓存资源作出更新,状态码为200。若新时间与旧时间一致,说明资源未变化,返回状态码304 Not Modified,浏览器收到后,便可从缓存中取资源。下面是详细的步骤流程:

         1⃣️.  客户端根据具体路径获取资源,此时服务器端会将该资源的一些基本信息自动封装http对象(包含响应头,响应体),Expires 表示该资源什么时候过期,Last-Modified表示该资源最后修改时间。

        2⃣️.  浏览器拿到资源时,放入缓存中,等待用户使用。

        3⃣️.  当用户使用功能需要该资源时,先检查是强制缓存还是协商缓存,前者则直接取,若两者都有Last-Modified、Expires同时存在,以强制缓存优先。若只是协商缓存则再次向服务器发送相同路径的请求,此时的请求头中附带上该资源的最后修改时间

        4⃣️.  服务器根据路径,检查最新资源的基本信息,是否与请求的基本信息一致。若一致,返回结果304 NotModified,此时服务器不再返回资源,而是再冗余返回一份基本信息,表示客户端缓存资源可用。若不一致,则返回状态码200和最新资源,还有最新资源的基本信息。当请求失败,也就是后台服务器挂掉的时候,这里也是返回304,继续使用缓存旧资源。

      

      http1.0返回304示例如下:

      

    一、http1.1——使用Cache-Control,age,Etag

      在上张图片中我们发现返回头中有Cache-Control,Etag这些字段,其实这些也是服务器端对浏览器作缓存控制用到的字段,只不过是后来升级换代新加入的。在使用http1.0的时候我们发现,当本地时间与服务器端的时间不一致,或者是部署集群时,地域跨度太大,很容易引起缓存失效的问题,而且同时有两份修改时间一致的文件互相进行替换的时候,我们很难及时在浏览器端作出响应。因此我们在想,能不能直接设置一个时间段,而不是时间点的方式来对资源有效去作校验,使用资源内容的哈希值、散列值去校验资源变化,这便是http1.1。在http1.1中,还是会分为强制缓存、协商缓存两种方式,只不过对时间、内容的校验方法做了优化。

      强制缓存:1⃣️客户端请求地址路径第一次获取资源,此时服务器端在响应头中设置放入两个字段:age和Cache-Control。age用来表示资源在客户端缓存中存在了多久,因为是第一次获取到的资源,所以初始化为0。Cache-Control用来表示资源有效期,即它能在客户端缓存中存在多久,例如Cache-Control:max-age=3600 表示3600秒内,缓存中的资源都是有效的可以直接使用的。

            2⃣️在3600秒内,客户端请求相同路径时,强制从缓存获取,并返回状态码200。

            3⃣️一旦资源占据缓存的时间超过3600秒,客户端重新从服务器获取资源,返回状态码200。

      

      协商缓存:1⃣️客户端第一次获取资源时,服务器在返回头放入字段Cache-Control和Etag。此时的Cache-Control与强制缓存的有点不同,不再是max-age和时间段,而是一个字符串固定值"no-cache"。Etag中放入的值一般为资源内容的哈希或者散列值。与返回体中的资源一同返回给客户端,并将其持久化至缓存。

            2⃣️客户端需要再次用到这个地址路径下的资源时,先去缓存中查看该资源的Cache-Control的值,发现为"no-cache",这时客户端知道了,需要先去后台做资源是否发生变化的校验,于是将该资源的Etag值发给后台,这里Etag的字段名发生变化,变成If-None-Match。

            3⃣️后台接收请求旧Etag后与最新的Etag进行比较,若一致,返回304,若不一致,返回200,并在响应体中放一份最新资源,响应头中放一份最新Etag。

            4⃣️强制缓存与协商缓存并存时:即Cache-Control值为"max-age=3600,no-cache",以强制缓存优先。

      

      注:在上图中我们发现1.0和1.1两种写法并存,其实是为了更好的兼容低版本浏览器,因为两个版本各自校验并不冲突。

    参考资料:https://www.jianshu.com/p/54cc04190252  

  • 相关阅读:
    select在各个浏览器中的兼容性问题
    pc打开手机站提示切换为手机屏幕
    图片预加载
    div盒子水平垂直居中的方法
    如何检测该浏览器为微信浏览器
    小箭头的写法,z-index在ie7显示混乱问题
    微信a标签不跳转
    css font简写规则
    windows环境cmd下执行jar
    docker制作镜像步骤
  • 原文地址:https://www.cnblogs.com/jiangxiaoxi/p/11450793.html
Copyright © 2020-2023  润新知