浏览器-缓存机制

Posted natsu-cc

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浏览器-缓存机制相关的知识,希望对你有一定的参考价值。

前言:

浏览器缓存是前端开发中不可避免的问题,对于web应用来说,它是提升页面性能同时减少服务器压力的利器。浏览器的缓存机制也就是我们说的HTTP缓存机制,其机制是根据HTTP报文的缓存标识进行的。

浏览器缓存是什么:

简单来说,浏览器缓存其实就是浏览器保存通过HTTP获取的所有资源,是浏览器将网络资源存储在本地的一种行为。

在这里插入图片描述


概述:

说到缓存就需要先了解HTTP报文:
在这里插入图片描述

  • HTTP请求(Request)报文,报文格式为:请求行 – HTTP头(通用信息头,请求头,实体头) – 请求报文主体(只有POST才有报文主体)。

在这里插入图片描述

  • HTTP响应(Response)报文,报文格式为:状态行 – HTTP头(通用信息头,响应头,实体头) – 响应报文主体。

在这里插入图片描述

注意:

通用信息头指的是请求和响应报文都支持的头域,分别为Cache-Control、Connection、Date、Pragma、Transfer-Encoding、Upgrade、Via;实体头则是实体信息的实体头域,分别为Allow、Content-Base、Content-Encoding、Content-Language、Content-Length、Content-Location、Content-MD5、Content-Range、Content-Type、Etag、Expires、Last-Modified、extension-header。

缓存过程:

浏览器与服务器通信的方式为应答模式,即是:浏览器发起HTTP请求 – 服务器响应该请求。那么浏览器第一次向服务器发起该请求后拿到请求结果,会根据响应报文中HTTP头的缓存标识,决定是否缓存结果,是则将请求结果和缓存标识存入浏览器缓存中。

简单的请求过程如下图:(首次)
在这里插入图片描述
浏览器缓存机制的概括(总体):

  • 浏览器每次发起请求,都会先在浏览器缓存中查找该请求的结果以及缓存标识。会根据请求头的expire和cache-control判断是否命中强缓存,是则从缓存中读取资源,不会发送请求到服务器。
  • 如果没有命中强缓存,浏览器就会携带if-None-Match:上一次Etag的值和if-Modified-Since: 上一次last-modified的值,发送请求到服务器,验证是否命中协商缓存,如果命中,则继续从缓存中读取资源。
  • 如果没有命中缓存,则直接从服务器加载资源。

缓存资源存放的地方:

在这里插入图片描述

内存缓存(memory cache):

MemoryCache顾名思义,就是将资源缓存到内存中,等待下次访问时不需要重新下载资源,而直接从内存中获取。资源分成两类,一类是主资源,比如html页面,或者下载项,一类是派生资源,比如HTML页面中内嵌的图片或者脚本链接,分别对应代码中两个类:MainResourceLoader和SubresourceLoader。

特点:

  • 快读读取: 内存缓存会将编译解析后的文件直接存入改进程的内存中,占据该进程一定的内存资源,方便下次运行使用时的快速读取。
  • 时效性: 一旦该进程关闭,则该进程的内存会清空。

硬盘缓存(disk cache):

DiskCache顾名思义,就是将资源缓存到磁盘中,等待下次访问时不需要重新下载资源,而直接从磁盘中获取,它的直接操作对象为CurlCacheManager。

特点:

  • 硬盘缓存是直接将缓存写入硬盘中,读取缓存需要对该缓存存放的硬盘文件进行I/O操作,然后重新解析该缓存内容,读取复杂,速度比内存缓存(memory cache)慢。

访问缓存优先级:

  • 先在内存中查找,如果有,直接加载。
  • 如果内存中不存在,则在硬盘中查找,如果有直接加载。
  • 如果硬盘中也没有,那么就进行网络请求。
  • 请求获取的资源缓存到硬盘和内存。

浏览器缓存类型:

浏览器缓存策略分为两种:

  • 强缓存
  • 协商缓存

强制缓存优先于协商缓存进行!

强缓存:

浏览器在加载资源时,会先根据本地缓存资源的 Header 中的信息判断是否命中强缓存,如果命中则直接使用缓存中的资源不会再向服务器发送请求。

Header 中的信息指的是 Expires和 Cache-Control。

Expires:

该字段是 http1.0 时的规范,它的值为一个绝对时间的 GMT 格式的时间字符串,比如 Expires:Mon,18 Oct 2066 23:59:59 GMT。这个时间代表着这个资源的失效时间,在此时间之前,即命中缓存。Expires控制缓存的原理,是使用客户端的时间与服务器端返回的时间做对比,如果客户端与服务器端的时间发生误差(如时区不同,修改了客户端时间),那么强缓存就会失效。

Cache-Control:

Cache-Control 是 http1.1 时出现的 header 信息,主要是利用该字段的 max-age 值来进行判断,它是一个相对时间,例如 Cache-Control:max-age=3600,代表着资源的有效期是 3600 秒。

几个比较常用的设置值:

  • no-cache:需要进行协商缓存,发送请求到服务器确认是否使用缓存。
  • no-store:禁止使用缓存,每一次都要重新请求数据。
  • public:可以被所有的用户缓存,包括终端用户和 CDN 等中间代理服务器。
  • private:只能被终端用户的浏览器缓存,不允许 CDN 等中继缓存服务器对其缓存。
  • Cache-Control 与 Expires 可以在服务端配置同时启用,同时启用的时候 Cache-Control 优先级高。

Expires和Cache-Control:max-age=xxx 的作用是差不多的,区别就在于 Expires 是http1.0的产物,Cache-Control是http1.1的产物。

强制缓存的情况主要有三种:

  • 不存在该缓存结果和缓存标识,强制缓存失效,则直接向服务器发起请求
    在这里插入图片描述
  • 存在该缓存结果和缓存标识,但该结果已失效,强制缓存失效,则使用协商缓存:
    在这里插入图片描述
  • 存在该缓存结果和缓存标识,且该结果尚未失效,强制缓存生效,直接返回该结果:
    在这里插入图片描述

协商缓存:

协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存。

控制协商缓存的字段分别为: Last-Modified/if-Modified-Since 和 Etag/if-None-Match,其中 Etag/if-None-Match的优先级更高。

Last-Modify/If-Modify-Since:

Last-Modified 是服务器响应请求时,返回该资源文件在服务器最后被修改的时间。
if-Modified-Since则是客户端再次发起该请求时,携带上次返回的 Last-Modified值。

当服务器收到该请求,并且发现请求头有if-Modified-Since字段时,就会将该值与该资源在服务器的最后修改时间做对比,如果有更新就重新返回资源,状态码为200;如果没有更新,则返回304,继续使用缓存文件。

Etag / If-None-Match:

Etag是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成)。

If-None-Match是客户端再次发起该请求时,携带上次请求返回的Etag值

当服务器接收到请求,并且发现请求头有If-None-Match时,就会将该值与资源在服务器的Etag值做对比,一致则代表资源没有更新,返回304,使用缓存文件;不一致则重新返回资源文件,状态码为200。

协商缓存的情况主要有两种:

  • 协商缓存生效,返回304:
    在这里插入图片描述
  • 协商缓存失效,返回200和请求结果结果:
    在这里插入图片描述

注意:

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

禁止浏览器缓存:
  • 设置请求头。
  • 给请求资源增加一个版本号/随机数。
  • HTML中禁用缓存。

总结:
  • 首先是否命中强缓存,如果命中,就直接使用缓存。
  • 如果没有命中强缓存,就发请求到服务器检查是否命中协商缓存。
  • 如果命中协商缓存,服务器会返回 304 告诉浏览器使用本地缓存。
  • 否则,返回最新的资源。

以上是关于浏览器-缓存机制的主要内容,如果未能解决你的问题,请参考以下文章

HTTP学习彻底弄懂 Http 缓存机制 - 浏览器缓存机制详解

HTTP学习彻底弄懂 Http 缓存机制 - 浏览器缓存机制详解

Java缓存学习之二:浏览器缓存机制

HTTP缓存机制

http缓存机制

web前端缓存机制