浏览器-缓存机制
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 缓存机制 - 浏览器缓存机制详解