最近在项目中遇到了IE浏览器因缓存问题未能成功向后端发送GET
类型请求的bug,而后顺藤摸瓜顺便看了看缓存的知识,以为有必要总结一下。php
在前端开发中,性能一直都是被你们所重视的一点,然而判断一个网站的性能最直观的就是看网页打开的速度。其中提升网页反应速度的一个方式就是使用缓存。一个优秀的缓存策略能够缩短网页请求资源的距离,减小延迟,而且因为缓存文件能够重复利用,还能够减小带宽,下降网络负荷。css
web缓存是指一个web资源(如html页面,图片,js,数据等)存在于web服务器和客户端(浏览器)之间的副本。html
缓存会根据进来的请求保存输出内容的副本;当下一个请求来到的时候,若是是相同的URL,缓存会根据缓存机制决定是直接使用副本响应访问请求,仍是向源服务器再次发送请求。比较常见的就是浏览器会缓存访问过网站的网页,当再次访问这个URL地址的时候,若是网页没有更新,就不会再次下载网页,而是直接使用本地缓存的网页。只有当网站明确标识资源已经更新,浏览器才会再次下载网页。至于浏览器和网站服务器是如何标识网站页面是否更新的机制,将在后面介绍。前端
web缓存的做用显而易见:web
web缓存大体能够分为如下几种类型:数据库
浏览器经过代理服务器向源服务器发起请求的原理以下图:后端
浏览器先向代理服务器发起web请求,再将请求转发到源服务器。它属于共享缓存,因此不少地方均可以使用其缓存资源,所以对于节省流量有很大做用。浏览器
浏览器缓存是将文件保存在客户端,在同一个会话过程当中会检查缓存的副本是否足够新,在后退网页时,访问过的资源能够从浏览器缓存中拿出使用。经过减小服务器处理请求的数量,用户将得到更快的体验缓存
下面着重关注一下浏览器缓存。安全
全部的缓存都是基于一套规则来帮助他们决定何时使用缓存中的副本提供服务(假设有副本可用的状况下,未被销毁回收或者未被删除修改)。这些规则有的在协议中有定义(如HTTP协议1.0和1.1),有的则是由缓存的管理员设置(如DBA、浏览器的用户、代理服务器管理员或者应用开发者)。
对于浏览器端的缓存来说,这些规则是在HTTP协议头和HTML页面的Meta
标签中定义的。他们分别从新鲜度和校验值两个维度来规定浏览器是直接使用缓存中的副本,仍是须要去源服务器获取更新的版本。
新鲜度(过时机制):也就是缓存副本有效期。一个缓存副本必须知足如下任一条件,浏览器会认为它是有效的,足够新的,而直接从缓存中获取副本并渲染:
Meta
标签<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
上述代码的做用是告诉浏览器当前页面不被缓存,每次访问都须要去服务器拉取。使用上很简单,但只有部分浏览器能够支持,并且全部缓存代理服务器都不支持,由于代理不解析HTML内容自己。
能够经过这个页面测试你的浏览器是否支持:Pragma No-Cache Test。
一个URI的完整HTTP协议交互过程是由HTTP请求和HTTP响应组成的。有关HTTP详细内容可参考《Hypertext Transfer Protocol — HTTP/1.1》、《HTTP协议详解》等。
在HTTP请求和响应的消息报头中,常见的与缓存有关的消息报头有:
Cache-Control
cache-control的种类这么多,然而怎么使用它们呢:
max-age(单位为s)指定设置缓存最大的有效时间,定义的是时间长短。当浏览器向服务器发送请求后,在max-age这段时间里浏览器就不会再向服务器发送请求了。
咱们来找个资源看下。好比QQ推广上的css资源,max-age=3600,也就是说缓存有效期为3600秒(也就是1h)。因而在1小时内都会使用这个版本的资源,即便服务器上的资源发生了变化,浏览器也不会获得通知。max-age会覆盖掉Expires,后面会有讨论。
Cache-Control
与Expires
的做用一致,都是指明当前资源的有效期,控制浏览器是否直接从浏览器缓存取数据仍是从新发请求到服务器取数据。只不过Cache-Control
的选择更多,设置更细致,若是同时设置的话,其优先级高于Expires
。Last-Modified与ETag
Etag是服务器自动生成或者由开发者生成的对应资源在服务器端的惟一标识符,可以更加准确的控制缓存。Last-Modified与ETag是能够一块儿使用的,服务器会优先验证ETag,一致的状况下,才会继续比对Last-Modified,最后才决定是否返回304。
你可能会以为使用Last-Modified
已经足以让浏览器知道本地的缓存副本是否足够新,为何还须要Etag
(实体标识)呢?HTTP1.1中Etag的出现主要是为了解决几个Last-Modified比较难解决的问题:
Last-Modified/ETag
的状况下,浏览器再次访问统一URI的资源,仍是会发送请求到服务器询问文件是否已经修改,若是没有,服务器会只发送一个304回给浏览器,告诉浏览器直接从本身本地的缓存取数据;若是修改过那就整个数据从新发给浏览器;Cache-Control/Expires
则不一样,若是检测到本地的缓存仍是有效的时间范围内,浏览器直接使用本地副本,不会发送任何请求。二者一块儿使用时,Cache-Control/Expires
的优先级要高,即当本地副本根据Cache-Control/Expires
发现还在有效期内时,则不会再次发送请求去服务器询问修改时间Last-Modified
或实体标识Etag
了。Last-Modified/ETag
将可以很好利用304,从而减小响应开销。没法被浏览器缓存的请求:
一个用户发起一个静态资源请求的时候,浏览器会经过如下几步来获取并展现资源:
缓存行为主要由缓存策略决定,而缓存策略由内容拥有者设置。这些策略主要经过特定的HTTP头部来清晰地表达。
以上过程也能够被归纳为三个阶段:
用户在使用浏览器的时候,会有各类操做,好比输入地址后回车,按F5刷新等,这些行为会对缓存有什么影响呢?
经过上表咱们能够看到,当用户在按F5
进行刷新的时候,会忽略Expires/Cache-Control的设置,会再次发送请求去服务器请求,而Last-Modified/Etag仍是有效的,服务器会根据状况判断返回304仍是200;
而当用户使用Ctrl+F5
进行强制刷新的时候,只是全部的缓存机制都将失效,从新从服务器拉去资源。
网上的帖子大多深浅不一,甚至有些先后矛盾,在下的文章都是学习过程当中的总结,若是发现错误,欢迎留言指出~
参考:
Web缓存机制系列
浅谈web缓存
Web先后端缓存技术
浏览器缓存机制:不一样浏览器对用户操做行为处理比较
PS:欢迎你们关注个人公众号【前端下午茶】,一块儿加油吧~
另外能够加入「前端下午茶交流群」微信群,长按识别下面二维码便可加我好友,备注加群,我拉你入群~