在上一篇文章中,咱们讲到形成网络性能降低的主要缘由是延迟,而非带宽。那么为了更好地让咱们的网站能快速响应用户的请求,咱们就必须对一些经常使用资源进行缓存,
以避免每次用户访问都请求一遍,这也是网站性能优化比较重要的一个环节。css
现代浏览器都自带了HTTP缓存实现功能,咱们所要作的只是确保咱们正确地设置了HTTP响应头,以便指示浏览器什么时候缓存响应以及缓存多久。浏览器
首先说明一点,缓存并非说浏览器不会对该资源再次发起请求,每种缓存机制都有本身的过时策略,咱们经常看到的304状态码就表面该资源已被缓存了,但浏览器不知道有没有过时,
再次使用该资源的时候,会向服务器发起请求验证一遍,若是缓存资源有效,则会返回304状态码。最坏的状况下,则是该资源过时了,还得从新发起一次请求去获取。另外一种则是浏览
器连问都不问服务器,直接就从本地硬盘读取,此时能够看到浏览器给出的响应是200(from disk cache)。缓存
假设咱们有一份css资源,咱们在获取该资源一段时间后又刷新了页面,这时浏览器就会检查本地资源并查找以前的响应。但遗憾的是,该响应已通过期。此时,浏览器能够直接发起请求
从新去获取一份新的数据,但这样作效率实在是过低了。若资源自己改变了还好说,但若资源自己并无改变呢,从新获取一份数据成本过高。性能优化
这时ETag就是用来解决这个问题的,ETag能够看作是这个文件的hash值,只要文件内容没有改变,ETag值则不会变。客户端彻底不须要了解ETag是怎么生成的,只须要在下一次请求的
时候将ETag带上便可(浏览器发起请求时,if-None-Match中的值就是该ETag值),若该ETag与服务器匹配,则会返回304,告诉浏览器可使用该缓存,从而跳过再次下载过程。服务器
Cache-Control指令控制谁在什么条件下能够缓存响应以及能够缓存多久,如上面所说,有些资源咱们能够直接从本地磁盘获取(from disk cache),而无需再次发起请求询问服务器,这
即是Cache-Control的做用。Cache-Control是HTTP/1.1规范中定义的,如今基本用它来取代Expires。网络
"no-cache"表示必须与服务器确认返回的响应是否发生了变化,而后才能使用该响应来知足后续对同一资源的请求。该值能够配合ETag来使用,浏览器经过请求If-None-Match来向服务器
验证该资源是否过时,若资源未发生变化,则避免下载。性能
"no-store"则表示不管什么状况下,浏览器都不得缓存该资源,即使存在ETag也同样,每次都得从服务器中获取。优化
若是响应被标记为"public",则即便它有关联的 HTTP 身份验证,甚至响应状态代码一般没法缓存,也能够缓存响应。大多数状况下,“public”不是必需的,由于明确的缓存信息(例如“max-age”)
已表示响应是能够缓存的。网站
"private"表示响应只为单个用户缓存,所以不容许中间缓存对其进行缓存。例如,用户浏览器能够缓存包含用户私人信息的HTML网页,但CDN则不能够。spa
该值是Cache-Control中用得比较多的一个值,表示从请求的时间开始,容许获取的响应被缓存的最长时间(单位:秒)。例如,max-age设置为100,则表示该资源能够缓存100秒,100秒后,再次
请求该资源,浏览器则会携带ETag去询问服务器该资源是否过时。在该资源未过时时,访问该资源,浏览器则从本地磁盘获取,不会发起任何网络请求。
如上图所示,若是资源不须要缓存,咱们设置Cache-Control的值为no-store;若是资源须要缓存且每次都得向服务器验证,则为no-cache;若是中间设备能够缓存,设置为public,中间设备不
可缓存,设置为private;若是缓存有时间限制,咱们设置max-age的值。private与public的值能够与max-age同时使用,中间用分号隔开。
Expires头指定了一个日期/时间,在这个日期/时间以后,HTTP响应被认为是过期的,一个无效的日期,例如0也表示该资源过期。若是还设置了max-age,则该请求头会被忽略。
使用缓存最好的方式就是ETag配合Cache-Control,并设置相应的max-age,通常状况下,再也不建议使用Expires头。若是资源许久都不更新,max-age能够设置比较长的时间,可是这样会有个问题就是在缓存期间,该文件发生改变,但相应的客户端却仍是在使用旧版本,解决的方法就是每一个文件都带一个相应内容的hash值做为文件名。这样,即便文件缓存了,也能够获得更新。