You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When you visit a URL in Chrome, the HTML and the other assets(like images) on the page are stored locally in a memory and a disk cache. Chrome will use the memory cache first because it is much faster, but it will also store the page in a disk cache in case you quit your browser or it crashes, because the disk cache is persistent.
缓存的概念分很多种,本次讨论的主要就是前端缓存中的Http缓存。
缓存是怎么回事
前端发送请求主要经历以下三个过程,请求->处理->响应。
如果有多次请求就需要重复执行这个过程。
重复请求的过程
以下是一个重复请求的流程图:
从以上的流程图可以看书,如果用户重复请求同一资源的话,会对服务器资源造成浪费,服务器重复读取资源,发送给浏览器后浏览器重复下载,造成不必要的等待与消耗。
缓存读取的过程
缓存读取就是浏览器在向服务器请求资源之前,先查询一下本地缓存中是否存在需要的资源,如果存在,那便优先从缓存中读取。当缓存不存在或者过期,再向服务器发送请求。
如何开启Http缓存并对缓存进行设置,是本次讨论的关键。
缓存的类型
浏览器有如下常见的几个字段:
强制缓存和协商缓存
缓存方法可以分为强制缓存与协商缓存。
从字面理解,强制缓存的方式简单粗暴,给
cache
设置了过期时间,超过这个时间之后cache过期需要重新请求。上述字段中的expires
与cache-control
中的max-age
都属于强制缓存。协商缓存根据一系列条件来判断是否可以使用缓存。
强制缓存优先级高于协商缓存
强制缓存
expires
expires
给浏览器设置了一个绝对时间,当浏览器时间超过这个绝对时间之后,重新向服务器发送请求。Expires: Fri, 04 Jan 2019 12:00:00 GMT
这个方法简单直接,直接设定一个绝对的时间 (当前时间+缓存时间)。但是也存在隐患,例如浏览器当前时间是可以进行更改的,更改之后expires设置的绝对时间相对不准确,
cache
可能会出现长久不过期或者很快就过期的情况。cache-control: max-age
为了解决
expires
存在的问题,Http1.1版本中提出了cache-control: max-age
,该字段与expires
的缓存思路相同,都是设置了一个过期时间,不同的是max-age
设置的是相对缓存时间开始往后多久,因此不存在受日期不准确情况的影响。但是强制缓存存在一个问题,该缓存方式优先级高,如果在过期时间内缓存的资源在服务器上更新了,客服端不能及时获取最新的资源。
协商缓存
协商缓存解决了无法及时获取更新资源的问题。以下两组字段,都可以对资源做标识,由服务器做分析,如果未进行更新,那返回
304
状态码,从缓存中读取资源,否则重新请求资源。last-modify
last-modify告知了客户端上次修改该资源的时间,
Last-Modified: Wed, 02 Jan 2019 03:06:03 GMT
浏览器将这个值记录在
if-modify-since
中(浏览器自动记录了该字段信息),下一次请求相同资源时,与服务器返回的last-modify
进行比对,如果相等,则表示未修改,响应 304;反之,则表示修改了,响应 200 状态码,并返回数据。last-modify
以秒为单位进行更新,如果小于该单位高频进行更新的话,不适合采用该方法。ETag
ETag是对资源的特殊标识
Etag: W/"e563df87b65299122770e0a84ada084f"
请求该资源成功之后,将返回的
ETag
存入if-none-match
字段中(浏览器自动记录了该字段信息),同样在请求资源时传递给服务器,服务器查询该编码对应的资源有无更新,无更新返回304状态,更新返回200并重新请求。以下有个小例子,查询书籍更新:
当书籍信息查询之后,再次查询,服务器根据资源的
ETag
查询得知该资源没有进行更新,返回304状态码。更新返回的数据信息,再次查询,返回200状态码,重新进行请求:
从返回的Request Headers可以看出,再次请求时,浏览器自动发送了
If-Modified-Since
与If-None-Match
两个字段,浏览器根据这两个字段中(If-None-Match
优先级大于If-Modified-Since
)来判断是否修改了资源。ETag如何计算
ETag
是针对某个文件的特殊标识,服务器默认采用SHA256
算法生成。也可以采用其他方式,保证编码的唯一性即可。缓存的优先级
根据上文优缺点的比对,可以得出以下的优先级顺序:
Cache-Control > Expires > ETag > Last-Modified
如果资源需要用到强制缓存,
Cache-Control
相对更加安全,协商缓存中利用ETag
查询更新更加全面。图片来源:浏览器缓存机制详解
缓存存储在哪
disk cache
disk cache
为存储在硬盘中的缓存,存储在硬盘中的资源相对稳定,不会随着tab或浏览器的关闭而消失,可以用来存储大型的,需长久使用的资源。当硬盘中的资源被加载时,内存中也存储了该资源,当下次改资源被调用时,会优先从
memory cache
中读取,加快资源的获取。memory cache
memory cache
即存储在内存中的缓存,内存中的内容会随着tab的关闭而释放。当接口状态返回304时,资源默认存储在
memory cache
中,当页面关闭后,重新打开需要再次请求。这两种存储方式的区别可以参考该回答
为什么有的资源一会from disk cache,一会from memory cache
三级缓存原理
为什么有的请求状态码返回200,有的返回304
200 from memory cache
不访问服务器,直接读缓存,从内存中读取缓存。此时的数据时缓存到内存中的,当关闭进程后,也就是浏览器关闭以后,数据将不存在。
但是这种方式只能缓存派生资源。
200 from disk cache
不访问服务器,直接读缓存,从磁盘中读取缓存,当关闭进程时,数据还是存在。
这种方式也只能缓存派生资源
304 Not Modified
访问服务器,发现数据没有
更新,服务器返回此状态码。然后从缓存中读取数据。
薄荷应用
举一个简单的小🌰,以薄荷的减肥群页面为讨论对象,查看一下资源加载的情况:
这些图片都是从硬盘中读取,因为没有在内存中获取到响应的资源,当我们刷新页面时,这个资源因为从硬盘中读取时,也存储到了内存中,再次获取就是从内存中获取了:
当我们没有关闭页面时,内存中的资源始终存在,重新打开则内存释放。
CDN缓存
CDN边缘节点缓存策略因服务商不同而不同,但一般都会遵循http标准协议,通过http响应头中的Cache-control: max-age的字段来设置CDN边缘节点数据缓存时间。
当客户端向CDN节点请求数据时,CDN节点会判断缓存数据是否过期,若缓存数据并没有过期,则直接将缓存数据返回给客户端;否则,CDN节点就会向源站发出回源请求,从源站拉取最新数据,更新本地缓存,并将最新数据返回给客户端。
如何合理应用缓存
强制缓存优先级最高,并且资源的改动在缓存有效期内都不会对缓存产生影响,因此该方法适用于大型且不易修改的的资源文件,例如第三方CSS、JS文件或图片资源,文件后可以加上
hash
进行版本的区分。建议将此类大型资源存入disk cache
,因为存在硬盘中的文件资源不易丢失。协商缓存灵活性高,适用于数据的缓存,根据上述方法的对比,采用
Etag
标识进行对比灵活度最高,并考虑将数据存入内存中,因为内存加载速最快,并且数据体积小,不会占用大量内存资源。广而告之
本文发布于薄荷前端周刊,欢迎Watch & Star ★,转载请注明出处。
欢迎讨论,点个赞再走吧 。◕‿◕。 ~
The text was updated successfully, but these errors were encountered: