浏览器缓存浅析

目录

缓存的介绍

缓存的分类

浏览器缓存的特点

浏览器缓存策略图

浏览器缓存协议头介绍

Expires

Cache-Control

Last-Modified / If-Modified-Since

ETag / If-None-Match

Etag出现的原因

缓存的优先级、强制不缓存及更新缓存

浏览器缓存常规设置

浏览器缓存demo

缓存的介绍

缓存的分类:

DNS域名解析缓存

Web服务器缓存(如:Nginx、Apache、Tomcat等)

CDN内容分发缓存

终端缓存(如:浏览器缓存、客户端缓存等)

etc...

浏览器缓存的特点

浏览器缓存是依赖于http协议的

不同的浏览器稍微有点区别

缓存是保存在浏览器中的;所以同一个浏览器,就算新开tab也是返回304;把浏览器退出重新打开,也是返回304;

浏览器缓存策略图

浏览器缓存协议头介绍

Expires

设置资源的过期时间

Cache-Control

设置资源的缓存时间

Last-Modified / If-Modified-Since

设置资源的最后修改时间

ETag / If-None-Match

设置资源的内容hash

Expires

简介:

`http/1.0`规范定义,其值为某个日期,规定这个日期之前都返回缓存,不请求服务器;

Expires = max-age + "每次下载时的当前的request时间",所以一旦重新下载的页面后,expires就重新计算一次

缺点:

没过设置的时间时,就算资源更新了,还是返回缓存

其值为服务器端的时间,如果浏览器所在机器的时间与服务器的时间相差很大(比如更改客户端时间),那么误差就很大

例子:

Expires: Mon, 08 Jan 2018 03:24:01 GMT

Cache-Control

简介:

其值为秒数,规定资源缓存多少秒,存储的是更新间隔;

设置Cache-Control时,为了保证向前兼容,都会同时设置Expires;

缺点:

同样有Expires一样的缺点:没过设置的时间时,就算资源更新了,还是返回缓存

只能精确到秒,资源有可能在1秒钟修改多次,导致返回的数据不准确

例子:

Cache-Control:max-age=15552000

Last-Modified

简介:

对应请求头中的`If-Modified-Since`;

其值是某个日期,表示文档的最后修改时间;

最后修改时间没变,直接返回304,只返回头部,不返回资源body;

流程:

第一次请求时,服务器会将资源的最后修改时间返回给浏览器,再请求时,浏览器会发送`If-Modified-Since`到服务器再对比

缺点:

会影响性能,因为每次请求后端都需要获取文件夹的最后修改时间

也只能精确到秒,但是比Cache-Control精确,因为每次请求浏览器都会把`If-Modified-Since`发送给服务器对比,然后确定返回200还是304,而Cache-Control是直接规定了多少秒,没过这个秒,不发送请求,浏览器直接from cache

例子:

Last-Modified:Wed, 22 Nov 2017 03:54:37 GMT

ETag

简介:

对应请求头中的`If-None-Match`

资源内容的hash,内容变了,Etag就会变;

流程:

第一次请求时,服务器会对资源内容(全部内容或者部分内容)进行hash,并把其传给浏览器,再请求时,浏览器会发送`If-None-Match`到服务器再对比,然后确定返回200还是304

缺点:

会影响性能,因为每次请求后端都需要读取文件内容并hash

例子:

Etag:QJ8ihycuJKpVTLT5xiQQhNT1Iec=

Etag出现的原因

Last-Modified已经足以让浏览器知道本地的缓存副本是否足够新,为什么还需要Etag?

`Last-Modified`标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内,被修改多次的话,它将不能准确标注文件的新鲜度

如果某些文件会被定期生成,当有时内容并没有任何变化,但`Last-Modified`却改变了,导致文件没法使用缓存

有可能存在服务器没有准确获取文件修改时间,或者与代理服务器(如Nginx)时间不一致等情形

缓存的优先级、强制不缓存及更新缓存

优先级

ETag(Last-Modified) > Cache-Control > Expires

Last-Modified与ETag同时使用时,浏览器会同时发送If-Modified-Since和If-None-Match,按照http/1.1规范,服务端必须两个都验证通过后才能返回304

强制不缓存

`Expires: 0` && `Cache-Control: 'no-cache,no-store'`

动态给资源添加版本控制,如:'index.js?v=' + Date.now()

强制更新缓存

如果文件变化了,我们可以给资源加版本号强制浏览器请求服务器(此时浏览器一定会下载资源返回200,因为URI变更后浏览器会当其为一个新资源)

浏览器缓存常规设置

首先设置**Expires** 和 **Cache-Control**,可以直接from cache (from memory cache 或 from disk cache),不用http链接;

`from memory cache`直接从内存读取缓存,从chrome中看,其请求时间都为0;退出进程时(关闭浏览器),数据会被清空

`from disk cache`是从硬盘读取缓存,从chrome中看,其请求时间都大于0;退出进程时(关闭浏览器),数据不会被清空

设置**Last-Modified**

设置Last-Modified的主要原因是:资源没变,但是Cache-Control的时间已经到了,这时浏览器不会fromcache,而是请求服务器,这时直接返回304,以节省带宽

浏览器缓存demo

Mid框架地址:https://github.com/xudeming208/mid

Etag测试demo地址:https://github.com/xudeming208/learning/tree/master/nodeJS/demo/cache/Etag

Expires、Cache-Control及Last-Modified

更改Mid框架中的配置文件,debug改为false

将静态文件服务器jserver.js中的maxAge改为30(秒)

启动Mid框架

观察network:

第一次为200(第一次请求下载资源)

第二为from cache(因为设置了Expires和Cache-Control)

等待30秒后,刷新浏览器,此时静态资源都变成304了(此时Cache-Control超过了30秒,缓存过时了,浏览器不会from cache,而会请求服务器,但是资源没变化,所以命中了Last-Modified,返回304)

Etag

node node.js

打开浏览器观察,第一次应该返回200,response headers中有Etag字段,request headers中没有If-None-Match字段

刷新页面,返回304,response headers中没有Etag字段,request headers中有If-None-Match字段,其值是第一次Etag的值

改变test.js的内容,再刷新页面,返回200,代表重新返回内容了,这时response headers中有Etag字段,但是值变了,request headers中有If-None-Match字段,其值还是第一次返回的Etag的值,两个值不一样

在刷新页面,结果和第三步一样

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180301G13SW800?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券