前言
在熟悉浏览器缓存前,我们先啰嗦一下DNS
以及CDN
缓存。虽说这两者不属于浏览器缓存,但在一定程度上也会影响前端开发以及问题的定位,如果不适当了解一些,当出现问题的时候也会有点摸不着
头脑。比如更新了服务端js文件,但是客户端死命的刷新,哪怕强制清除缓存后再刷新,文件内容还是没改变。这种问题大概率是中间商
在作祟——CDN
没更新。
DNS缓存
通过域名最终得到IP地址的过程叫做域名解析
。有解析的地方就会存在缓存,从客户端的角度去看,大概可以分为四个范围,也是DNS
查询的一个过程:
- 1、浏览器查询自身的
DNS缓存
,如果查到,则解析结束直接返回域名对应的IP地址; - 2、从当前操作系统中查找,如果
host
文件中存在对应关系,则解析结束返回对应的IP地址; - 3、查找本地对应的
DNS服务器
,如果查找不到则继续; - 4、向根服务器发起请求,查找域名对应的IP地址关系。
以上情况大体了解即可,毕竟前端对DNS缓存
几乎啥都不能做。
CDN缓存
什么是CDN?其实就是一个代理
。比如一个跨国公司在中国开设业务,国内业务员每次汇报工作都要跟老外联系,这一来一回想必几天就过去了,效率如此之低。这个时候跨国公司如果在中国设立一个大中华区
,每次汇报工作只要跟国内负责人联系即可。这个大中华区
总裁就可以理解为代理
,在国内业务员看来代理
等同于老外。
其实简单的理解就是CDN
相当于服务器的一个个拷贝,内容等同于根服务器上的内容,只是距离用户更近了,这样不仅可以节省网络请求的时间,还可以减轻根服务器的压力。这样的优势固然很好,但凡是都有两面性,有可能会产生服务端更新了文件但是CDN
没有更新的情况,这样用户访问的时候仍然会访问过期的资源。
如何解决CDN
更新问题?
- 1、主动刷新。一般CDN运营商,都会提供一个后台,主动刷新文件内容。就是让
中间
服务器主动去根服务器拉取更新内容。 - 2、修改
query string
值。比如更新一个图片,在图片URL地址后增加一个?v=123
的参数,这个时候相当于中间服务器没有缓存,需要重新拉取根服务器图片。
缓存的加载顺序一般是先从内存中寻找,如果没有则从硬盘中寻找,再没有的话就从网络层面查找。
强缓存
不向服务器发送请求,每次都从本地缓存中加载资源文件。那么如何区分文件是从网路请求的还是本地的呢?从chrome浏览器开发者工具中的network
栏目中可以看到如下图片,Size
来源分三种情况:
- 1、若显示类似
12kB
字样,则表示从网络上请求得到; - 2、若显示
memory cache
则表示从内存中得到; - 3、若显示
disk cache
则表示从磁盘缓存中加载的资源。
那么什么情况下才会命中强缓存呢?在HTTP/1.1中,请求资源返回头(Response Headers)会有这么一个字段cache-control
,假如值是max-age=600
,则表示在这次请求后未来的10分钟内若再次请求该资源时,则无需从服务端加载,只要加载本地资源即可,这就算命中强缓存了。cache-control
会有多个值,不同的值代表不同的意思:
- 1、
public
表明相应可以被任何对象(客户端、CDN中间代理商等)缓存,即使是通常不可缓存的内容; - 2、
private
只有客户端(例如浏览器)才可以缓存(cache-control默认值); - 3、
no-cache
可以被缓存(注意不要被字面意思误解了),只是使用缓存的时候需要与服务端协商是否能够使用,后面“协商缓存”会讲到; - 4、
no-store
告诉浏览器不能缓存,每次都要从服务端拉取; - 5、
max-age
表示多少秒内缓存即将消失,是一个相对时间; - 6、
s-maxage
表示中间代理商缓存文件的有效期,例如cdn
在这个时间之后需要重新拉取根服务器上的资源。
目前常见的也就上面6种情况,其他的暂不需要记忆,等需要的时候再查询也来得及。
有一点要特殊说明一下:http1时代的产物
Expires
字段会返回一个绝对时间,用于表示那个时间之前会命中强缓存,之后资源缓存将失效。但这种方法有很大的弊端,因为是绝对时间,当服务器时间与客户端时间相差较大的时候会产生混乱。且目前基本上不再使用,所以只要了解一下即可。
协商缓存
协商缓存就是当强缓存失效以后,浏览器携带一些标识
再次向服务器发起请求,由服务器决定是继续使用缓存内容,还是重新拉取新资源。这里的一些标识
主要是指这两对关键词:
- 1、
ETag
和If-None-Match
- 2、
Last-Modified
和If-Modified-Since
其中ETag
和Last-Modified
是请求资源时返回的头信息之一,分别表示资源的唯一标识
和文件的最后修改时间
。请求的资源发生变动的时候,这两个值都会修改。当没有命中强缓存的时候,浏览器会将这两个值分别以If-None-Match
和If-Modified-Since
作为request
请求头之一回传给服务器。服务器会先将收到的ETag
值与当前文件ETag
进行比对,若不同则表示浏览器缓存的文件过期,则会返回200
状态码,同时将最新文件以及标识符返回给客户端。若ETag
值相同则比对最后修改时间,若还是一致则表示文件没有更新,则返回304
状态码表示文件未更新,缓存文件可继续使用。