前端技术分享-码匠 极客编程技术分享

您当前位于:项目开发经验 ——> 浏览器的缓存问题 - 缓存有哪些种类,会造成什么影响,如何处理缓存问题?

浏览器的缓存问题 - 缓存有哪些种类,会造成什么影响,如何处理缓存问题?

2017/03/09 09:52:00 | 作者:HTML5学堂(码匠) | 分类:项目开发经验 | 关键词:浏览器缓存,Expires,缓存机制,缓存问题,缓存

本文内容概要:

1 Web缓存是什么?为什么要使用它?

2 Web缓存的类型

3 浏览器缓存的基本知识

3.1 Expires

3.2 Last-modified

3.3 Cache-Control

3.4 ETag

4 浏览器缓存机制

4.1 强缓存应用

4.2 协商缓存应用

4.3 强缓存与协商缓存的区别

5 浏览器缓存的流程

6 浏览器缓存的优化

1 Web缓存是什么?为什么要使用它

Web缓存是介于服务器与客户端之间。服务器可能是源服务器(因为中间可能会有代理服务器),就是网站资源所在的服务器。客户端指的是我们的浏览器。Web缓存就是在服务器和客户端之间搞监督,监督请求,并把请求的结果传给浏览器显示出来,另外存储一份(我们称为副本,也就是缓存)。然后,我们下次请求相同的URL路径,直接请求保存的副本(缓存),而不是再次向源服务器获取数据。

缓存的好处:

优秀的缓存策略可以缩短网页请求资源的距离,从而减少延迟时间,并且由于缓存文件可以重复利用,还可以减少带宽,降低网络负荷。

Tips:带宽是指在单位时间(一般指的是1秒钟)内能传输的数据量。网络和高速公路类似,带宽越大,就类似高速公路的车道越多,其同行能力越强。

欢迎沟通交流~HTML5学堂(码匠)

2 Web缓存的类型

2.1 浏览器缓存

通过使用HTTP协议与服务器交互的时候,浏览器就会根据一套与服务器约定的规则进行缓存工作。

2.2 代理服务器缓存

代理服务器是浏览器和源服务器之间的中间服务器,浏览器先向这个中间服务器发起Web请求,经过处理后(比如权限验证,缓存匹配等),再将请求转发到源服务器。

2.3 数据库缓存

当Web应用逻辑较为复杂,频繁进行数据库查询,很容易导致数据库不堪重荷。为了提高查询的性能,将查询后的数据放到内存中进行缓存,下次查询时,直接从内存缓存直接返回,提高响应效率。

2.4 应用层缓存

通过代码逻辑,把之前请求过的数据缓存起来,再次需要数据时通过逻辑上的处理选择可用的缓存的数据。

今天我们要给大家讲解的是浏览器缓存,先来看看浏览器缓存的基本知识。

3 浏览器缓存的基本知识

浏览器的缓存状态是由HTTP header决定的,header的参数有四种:Expires、Last-modified、Cache-Control、ETag;

3.1 Expires

缓存过期时间,用来指定资源到期的时间,是服务器端的具体的时间点,在响应http请求时告诉浏览器在过期时间前浏览器可以直接从浏览器缓存取数据,而无需再次请求。

HTML5学堂(码匠) - 缓存 - expires

3.2 Last-modified

服务器端文件的最后修改时间,需要和Cache-Control共同使用,是检查服务器端资源是否更新的一种方式。当浏览器再次进行请求时,会向服务器传送If-Modified-Since报头,询问Last-Modified时间点之后资源是否被修改过。如果没有修改,则返回码为304,使用缓存;如果修改过,则再次去服务器请求资源,返回码和首次请求相同为200,资源为服务器最新资源。

HTML5学堂(码匠) - 缓存 - last-modified

3.3 Cache-Control

max-age(单位为s):指定设置缓存最大的有效时间,定义的是时间长短。比如Cache-Control:max-age=200表示文件在浏览器应该缓存且有效时长是200秒(从发出请求算起)。在接下来200秒内,如果有再次请求这个资源,浏览器不会向服务器发出HTTP请求,而是直接使用浏览器缓存下来的文件。

HTML5学堂(码匠) - 缓存 - max-age

3.4 ETag

ETag和Last-Modified也是一样的,是对文件进行标识的字段。不同的是,ETag是根据实体内容生成一段hash字符串,标识资源的状态,由服务端产生。在向服务器查询文件是否有更新时,浏览器通过If-None-Match字段把特征字串(hash字符串)发送给服务器,由服务器和文件最新特征字串进行匹配,来判断文件是否有更新。没有更新则返回304,有更新则返回200。ETag和Last-Modified可根据需求使用一个或两个同时使用。两个同时使用时,只要满足基中一个条件,就认为文件没有更新。

HTML5学堂(码匠) - 缓存 - ETag

3.5 四种参数的对比

HTML5学堂(码匠) - 缓存 - HTTP head的对比

欢迎沟通交流~HTML5学堂(码匠)

4 浏览器缓存机制

4.1 强缓存应用

1 浏览器第一次向服务器请求一个资源时,服务器返回这个资源的同时,在respone的header加上Expires的header;

2 浏览器在接收到这个资源后,会把这个资源连同所有response header一起缓存下来(所以符合条件的缓存请求返回的header并不是来自服务器,而是来自之前缓存的header);

3 浏览器再请求这个资源时,先从缓存中寻找,找到这个资源后,拿出它的Expires跟当前的请求时间比较,如果请求时间在Expires指定的时间之前,就符合缓存要求,否则向服务器请求资源;

4 如果没有符合缓存的要求,浏览器直接从服务器加载资源时,Expires Header在重新加载的时候会被更新;

Expires的一个缺点就是,返回的到期时间是服务器端的时间,这样存在一个问题,如果客户端的时间与服务器的时间相差很大(比如:客户端的时间是2016.07.01 21:05.07,而服务器的时间是2016.07.12 12:15.07,缓存过期的时间是2016.07.23 20:05.07,这样会产生延迟过期),那么误差就很大,另外一个问题是,你很容易忘记给某内容设置了一个特定时间,如果返回内容的时候没有更新这个过期时间(Expires),则每个请求都是访问到服务器,反而增加了负载和响应时间。所以在HTTP 1.1版开始,使用Cache-Control: max-age来进行替代。

注意:

max-age是根据它第一次的请求时间和Cache-Control设定的有效期,计算出一个资源过期时间,再拿这个过期时间跟当前的请求时间比较,如果请求时间在过期时间之前,就符合缓存要求,否则就不行。

Expires和Cache-Control同时存在时,Cache-Control优先级高于Expires;

强缓存通常都是针对静态资源使用,动态资源需要慎用,除了服务端页面可以看作动态资源外,那些引用静态资源的html也可以看作是动态资源,如果这种html也被缓存,当这些html更新之后,可能就没有机制能够通知浏览器这些html有更新,尤其是前后端分离的应用里,页面都是纯html页面,每个访问地址可能都是直接访问html页面,这些页面通常不加强缓存,以保证浏览器访问这些页面时始终请求服务器最新的资源。

4.2 协商缓存应用

1 浏览器第一次跟服务器请求一个资源,服务器在返回这个资源的同时,在respone的header加上Last-Modified的header,这个header表示这个资源在服务器上的最后修改时间;

2 浏览器再次向服务器请求这个资源时,在request的header上加上If-Modified-Since的header,这个header的值就是上一次请求时返回的Last-Modified的值;

HTML5学堂(码匠) - 缓存 - If-Modified-Since

3 服务器再次收到资源请求时,根据浏览器传过来If-Modified-Since和资源在服务器上的最后修改时间判断资源是否有变化,如果没有变化则返回304 Not Modified,但是不会返回资源内容;如果有变化,就正常返回资源内容。当服务器返回304 Not Modified的响应时,response header中不会再添加Last-Modified的header,因为既然资源没有变化,那么Last-Modified也就不会改变,这是服务器返回304时的response header;

4 浏览器收到304的响应后,就会从缓存中加载资源;

5 如果不符合协商缓存要求,浏览器直接从服务器加载资源时,Last-Modified Header在重新加载的时候会被更新,下次请求时,If-Modified-Since会启用上次返回的Last-Modified值。

Last-Modified和If-Modified-Since都是根据服务器时间返回的header,一般来说,在没有调整服务器时间和篡改客户端缓存的情况下,这两个header配合起来管理协商缓存是非常可靠的,但是有时候也会服务器上资源其实有变化,但是最后修改时间却没有变化的情况,而这种问题又很不容易被定位出来,而当这种情况出现的时候,就会影响协商缓存的可靠性。所以就有了另外一对header来管理协商缓存,这对header就是ETag和If-None-Match。

1 浏览器第一次向服务器请求一个资源,服务器在返回这个资源的同时,在respone的header加上ETag的header,这个header是服务器根据当前请求的资源生成的一个唯一标识,这个唯一标识是一个字符串,只要资源有变化这个串就不同,跟最后修改时间没有关系,所以能很好的补充Last-Modified的问题;

2 浏览器再次跟服务器请求这个资源时,在request的header上加上If-None-Match的header,这个header的值就是上一次请求时返回的ETag的值;

3 服务器再次收到资源请求时,根据浏览器传过来If-None-Match和然后再根据资源生成一个新的ETag,如果这两个值相同就说明资源没有变化,否则就是有变化;如果没有变化则返回304 Not Modified,但是不会返回资源内容;如果有变化,就正常返回资源内容。与Last-Modified不一样的是,当服务器返回304 Not Modified的响应时,由于ETag重新生成过,response header中还会把这个ETag返回,即使这个ETag跟之前的没有变化;

4 浏览器收到304的响应后,就会从缓存中加载资源;

注意:

大部分Web服务器都默认开启协商缓存,而且是同时启用Last-Modified和If-Modified-Since、ETag和If-None-Match这也是为了处理Last-Modified不可靠的情况;

协商缓存需要配合强缓存使用,因为如果不启用强缓存的话,协商缓存根本没有意义;

4.3 强缓存与协商缓存的区别

共同点:如果符合条件,都是从客户端缓存中加载资源,而不是从服务器加载资源数据;

不同点:强缓存不发送请求到服务器,协商缓存会发送请求到服务器;

5 浏览器缓存的流程

HTML5学堂(码匠) - 缓存 - 浏览器缓存流程

6 浏览器缓存的优化

Last-Modified 需要向服务器发起查询请求,才能知道资源文件有没有更新。虽然服务器可能返回304告诉没有更新,但也还有一个请求的过程。对于移动网络,这个请求可能是比较耗时的。有一种说法叫“消灭304”,指的就是优化掉304的请求。

在实际应用中,为了解决 Cache-Control 缓存时长不好设置的问题,以及为了”消灭304“,Web前端采用的方式是:

1 在要缓存的资源文件名中加上文件MD5值字串,如 common.d5d02a02.css,同时设置 Cache-Control:max-age=31536000,也就是一年。在一年时间内,资源文件如果本地有缓存,就会使用缓存;也就不会有304的回包。

2 如果资源文件有修改,则更新文件内容,同时修改资源文件名,如 common.d5d02a02.cs,html页面就会引用新的资源文件名。

学习资料:

流云诸葛

张鑫旭-鑫空间-鑫生活

大额大额哼歌等日落的博客

腾讯全端 AlloyTeam 团队 Blog

欢迎沟通交流~HTML5学堂(码匠)

HTML5学堂微信~欢迎扫码关注

HTML5学堂微信

微信公众号,HTML5学堂,码匠,原创文章,WEB前端,技术分享

HTML5学堂

原创前端技术分享

HTML5学堂,HTML5,WEB,前端,视频课程,技术视频,学习视频,面试,JS

原创视频课程

用心打造精品课程

微信小程序,决胜前端,面试题,面试题集合,前端,HTML5,真题

小程序-决胜前端

前端面试题宝库

原创书籍,学习书籍,书籍推荐,HTML5布局之路,HTML5,WEB前端

HTML5布局之路

非传统模式讲解前端