咱们都知道对页面进行缓存可以有利于减小请求发送,从而达到对页面的优化。不过在我前端工做的生涯中一直觉得前端就是写写页面,写写交互,就已经很了不得,这种没有志向的想法发致使我往后的工做一直处于瓶颈。作人嘛总要有梦想嘛,否则跟一条咸鱼有什么区别。最近我一直在关于前端优化的问题,原来对页面进行有效缓存对于响应速度会大大提升。我也是综合本身看到的几篇文章,谈谈见解,权当是一次学习笔记吧,有什么不对的请多多包涵。废话很少说,开始正题。php
缓存机制
html
缓存分为服务端侧(server side,好比 Nginx、Apache)和客户端侧(client side,好比 web browser)。
前端
服务端缓存又分为 代理服务器缓存 和 反向代理服务器缓存(也叫网关缓存,好比 Nginx反向代理、Squid等),其实普遍使用的 CDN 也是一种服务端缓存,目的都是让用户的请求走”捷径“,而且都是缓存图片、文件等静态资源。
浏览器缓存控制机制有两种:HTML Meta标签 vs. HTTP头信息
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
上述代码的做用是告诉浏览器当前页面不被缓存,每次访问都须要去服务器拉取。使用上很简单,但只有部分浏览器能够支持,并且全部缓存代理服务器都不支持,由于代理不解析HTML内容自己。
web
一、服务端缓存相关api
什么是Etag?什么是Last-Modified?等等这些,都是什么鬼,之前我一看到都是直接懵逼。浏览器
首先咱们要先根据http请求头以及响应头 先看一些跟缓存相关的报文头cache-control, if-none-match, if-modified-since, Etag,expires, last-modified,
request header缓存相关:
cache-control:
其缓存指令对于前段经常使用的有以下no-cache、no-store、max-age这几个值;分别来讲一下
no-cache:
表面意为“数据内容不被缓存”,而实际数据是被缓存到本地的,只是每次请求时候直接绕过缓存这一环节直接向服务器请求最新资源,因为浏览器解释不同,
例如ie中咱们设置了no-cache以后,请求虽然不会直接使用缓存,可是还会用缓存数据与服务器数据进行一致性检测(也就是说仍是有概率会用到缓存的),
firefox中则彻底无视no-cache存在,详细解释见no-store;
no-store:
指示缓存不存储这次请求的响应部分。与no-cache比较来讲,一个是不用缓存,一个是不存储缓存;按理来讲这个设置更加粗暴直接禁用缓存,
可是具体实现起来 浏览器之间差别却特别大,通常不会直接用该字段进行设置,不过no-store是为了防止缓存被恶意修改存储路径致使信息被泄露而设置的,
毕竟有它的用处,在firefox中实现缓存是经过文件另存为将缓存副本保存到本地,直接利用no-cache对其是无效的,若是加上no-store设置的话 则能够起到与no-cache同样的效果;
即:cache-control:no-cache,no-store;能够确保在支持http1.1版本中各大浏览器回车后退刷新无缓存;
再加上Pragma: no-cache设置兼容版本1.0便可(不过为了防止一致性检测时候的万一咱们仍是最好加上一致性检测的内容,以下所示几种方式);
max-age:
例如Cache-control: max-age=3;表示这次请求成功后3秒以内发送一样请求不会去服务器从新请求,而是使用本地缓存;一样咱们若是设置max-age=0表示当即抛弃缓存直接发送请求到服务器
一致性检测分为两种方式:1.检测日期是否过时,检测资源是否更新;
if-none-match:
该字段与响应中的eTag一块儿使用,表示检查实体是否有更新改变;客户端第一次发送请求时候响应报文会包含字段Etag,表示资源状态,当资源改变后该值也会改变(客户端没必要关心该值怎么生成)
而后缓存保存下该字段,第二次已经有该缓存时候在浏览本地缓存时候会将该值赋给if-none-match字段发送给服务器,服务器将发送的值与当前的状态进行对比,
若是值同样的话则答复304去使用缓存数据,若是值改变了则发送最新数据给客户端替代现有缓存数据,而且返回状态200;
if-modified-since:
该字段与last-modified配合使用,跟上述原理差很少,都是响应端先返回一个last-modified时间字段,再次请求时候 request头部会将缓存中的last-modified字段拿出来赋给if-modified-since,
发送给服务器,服务器去判断时间是否过时,如未过时则返回304,告诉客户使用缓存数据,若是过时则从新返回一个last-modified而且返回200;
repsonse header缓存相关:
Etag:
刚才也说过 是跟if-none-match配合去使用,它根据实体内容生成的一段hash字符串(相似于MD5或者SHA1以后的结果),能够标识资源的状态。 当资源发送改变时,ETag也随之发生变化。
使用Etag主要是为了解决根据时间没法解决的问题:好比文件修改频繁(秒以内修改),致使根据时间没法判断是否更新;以及修改时间变了,可是内容没变(咱们应该认为该文件是没变的)
expires:
表示缓存过时时间例如:expires:Mon Dec 30 2011 11:01:19 GMT,跟cache-control中的max-age做用同样,不过在遇见max-age以后,该值会被覆盖从而被max-age替代;
last-modified:
表示文件最后修改时间;
另外响应端的报文头也有对cache-content的规定,与request大致相同,另有未说起的 欢迎你们补充
缓存
使用缓存:服务器
默认状况下,浏览器都会使用缓存数据,网络
在f5刷新状况下 浏览器会发送一致性验证去服务器验证是否使用缓存,而浏览器直接回车则表示直接应用缓存不须要去服务器验证;因此咱们就按照f5刷新去解释实现使用缓存:dom
通常来讲前端默认是使用缓存的,默认状况下服务器端以及前端都会使用缓存数据,或者是根据etag或者是根据max-age或者是根据expires根据服务器不一样去不一样实现;
实际中大部分不须要咱们手动去实现,而有些咱们不肯定是否使用缓存的状况下咱们能够手动加以干涉强制使用缓存数据:
例如某个静态文件包括html或者图片咱们须要使用缓存来提升处理速度,
方法一:
在服务器进行配置其max-age或者expires使其设置一个过时值为当前一年以后。这样每次进行检验时候都会使用缓存中文件.例如在.htaccess中
<IfModule mod_headers.c>
<FilesMatch ".(gif|jpg|jpeg|png|ico)$">
Header set Cache-Control "max-age=604800"
</FilesMatch>
方法二:
前端设置if-modified-since去设置一个上次修改时间大于当前日期,
方法三:
服务器端根据etag去判断是否匹配来根据实际业务来使用缓存;
后面两个方法属于弱缓存数据头,须要浪费http链接,因此建议使用第一种方式;
禁用缓存:
方法一:
能够在meta标签标明<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
方法二:
也能够动态去setRequestHeader,强制不用缓存设置组合以下:
cache-control='no-cache,no-store'
pragma='no-cache'
if-modified-since=0;
方法三:
请求端设置if-modified-since为已通过期的某个时间,能够是几年前或者几十年前。
方法四:
服务端设置Expires为过时某个时间,例如php中header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
实际开发中若是须要一致性检测则尽可能去配合Etag以及last-Modified去进行比较而后返回使用缓存仍是新数据;这个有点偏服务器端了,再也不赘述
方法五:
url后面加随机数或者时间戳url += “&random=” + Math.random()这个方法js以及php常常用,原理就是每一个请求的url都不同这样一来缓存中找不到对应数据,就自动去服务器寻找最新资源;
二、浏览器缓存相关
浏览器缓存是浏览器端保存数据用于快速读取或避免重复资源请求的优化机制,有效的缓存使用能够避免重复的网络请求和浏览器快速地读取本地数据,总体上加速网页展现给用户。浏览器端缓存的机制种类较多,打开浏览器的调试模式->resources左侧就有浏览器的8种缓存机制。
上述的缓存机制js都有相关的api进行操做,请自行查询。上面其实都是我粘贴复制的,由于这几篇文章让当时的我有种醍醐灌顶的感受。详情能够参考以下连接