浏览器缓存知识概括

浏览器缓存(Browser Catching)是为了节约网络的资源加速浏览,浏览器在用户磁盘上对最近请求过的文档进行存储,当访问者再次请求这个页面时,浏览器就能够从本地磁盘显示文档,这样就能够加速页面的阅览。 —-摘自《百度百科》css

浏览器缓存是提高网页性能的一大利器,可是,也是一把双刃剑。利用的好网页的性能会有大幅度提高,服务器的压力也会减少。利用的很差,也会遇到不少的问题。本文结合浏览器缓存的知识,结合真实案例进行分析,但愿对读者有所帮助。node

浏览器缓存分类浏览器

浏览器缓存分为强缓存和协商缓存,浏览器加载一个页面的简单流程以下:缓存

  1. 浏览器先根据这个资源的http头信息来判断是否命中强缓存。若是命中则直接加在缓存中的资源,并不会将请求发送到服务器。服务器

  2. 若是未命中强缓存,则浏览器会将资源加载请求发送到服务器。服务器来判断浏览器本地缓存是否失效。若可使用,则服务器并不会返回资源信息,浏览器继续从缓存加载资源。网络

  3. 若是未命中协商缓存,则服务器会将完整的资源返回给浏览器,浏览器加载新资源,并更新缓存。

强缓存ide

命中强缓存时,浏览器并不会将请求发送给服务器。在Chrome的开发者工具中看到http的返回码是200,可是在Size列会显示为(from cache)。函数

浏览器缓存知识概括
强缓存是利用http的返回头中的Expires或者Cache-Control两个字段来控制的,用来表示资源的缓存时间。工具


Expires
性能

该字段会返回一个时间,好比Expires:Thu,31 Dec 2037 23:59:59 GMT。这个时间表明着这个资源的失效时间,也就是说在2037年12月31日23点59分59秒以前都是有效的,即命中缓存。这种方式有一个明显的缺点,因为失效时间是一个绝对时间,因此当客户端本地时间被修改之后,服务器与客户端时间误差变大之后,就会致使缓存混乱。因而发展出了Cache-Control。

Cache-Control

Cache-Control是一个相对时间,例如Cache-Control:3600,表明着资源的有效期是3600秒。因为是相对时间,而且都是与客户端时间比较,因此服务器与客户端时间误差也不会致使问题。

Cache-Control与Expires能够在服务端配置同时启用或者启用任意一个,同时启用的时候Cache-Control优先级高。

协商缓存

若未命中强缓存,则浏览器会将请求发送至服务器。服务器根据http头信息中的Last-Modify/If-Modify-Since或Etag/If-None-Match来判断是否命中协商缓存。若是命中,则http返回码为304,浏览器从缓存中加载资源。

Last-Modify/If-Modify-Since

浏览器第一次请求一个资源的时候,服务器返回的header中会加上Last-Modify,Last-modify是一个时间标识该资源的最后修改时间,例如Last-Modify: Thu,31 Dec 2037 23:59:59 GMT。

浏览器缓存知识概括
当浏览器再次请求该资源时,上送的请求头中会包含If-Modify-Since,该值为缓存以前返回的Last-Modify。服务器收到If-Modify-Since后,根据资源的最后修改时间判断是否命中缓存。

浏览器缓存知识概括

若是命中缓存,则返回http304,而且不会返回资源内容,而且不会返回Last-Modify。因为对比的服务端时间,因此客户端与服务端时间差距不会致使问题。可是有时候经过最后修改时间来判断资源是否修改仍是不太准确(资源变化了最后修改时间也能够一致)。因而出现了ETag/If-None-Match。

ETag/If-None-Match

与Last-Modify/If-Modify-Since不一样的是,Etag/If-None-Match返回的是一个校验码(ETag: entity tag)。ETag能够保证每个资源是惟一的,资源变化都会致使ETag变化*。服务器根据浏览器上送的If-None-Match值来判断是否命中缓存。

浏览器缓存知识概括

* ETag扩展说明

咱们对ETag寄予厚望,但愿它对于每个url生成惟一的值,资源变化时ETag也发生变化。神秘的Etag是如何生成的呢?以Apache为例,ETag生成靠如下几种因子

  1. 文件的i-node编号,此i-node非彼iNode。是Linux/Unix用来识别文件的编号。是的,识别文件用的不是文件名。使用命令’ls –I’能够看到。

  2. 文件最后修改时间

  3. 文件大小

  4. 生成Etag的时候,可使用其中一种或几种因子,使用抗碰撞散列函数来生成。因此,理论上ETag也是会重复的,只是几率小到能够忽略。

生产问题分析

背景:某次投产,某系统投产后因为强缓存设置时间不恰当致使变动的功能没有体现。后来经过变动文件路径强行解决问题。

变动上下文根,致使URL变化必定能够解决问题。但咱们不可能每一次都这么作;还有,在浏览器端关闭缓存、或者清除缓存后再继续浏览、同时使用Ctrl+F5刷新,也能够解决问题,可是咱们也不可能让每个客户在投产后都作一次这个操做。

那咱们怎么办呢?从问题缘由来看,是将常常变化的资源缓存时间设置的过长致使的。理论上来说,只要正确划分常常变化资源与不常常变化资源就能够解决问题。可是谁也不能保证不常常变化的资源就必定不会变化。

万一不常常变化的资源变动了怎么办呢?在资源请求的URL中增长一个参数,好比:css/main.css?v=20160105。这个参数是一个版本号,客户化在js代码中,每一次投产的时候变动一下,当这个参数变化的时候,强缓存都会失效并从新加载。这样一来,即便是不常变化的资源,投产之后也须要从新加载。这样就完美的解决了问题。

本文参考数篇技术博客、百度百科、维基百科、Apache官方说明以及本身的理解完成,若有不正确的地方欢迎斧正。

相关文章
相关标签/搜索