浏览器的缓存机制

一、缓存机制概述

1. 基本概念介绍

浏览器缓存机制(即HTTP缓存机制),根据HTTP报文的缓存标识来决定使用缓存内容,还是重新从服务器获取最新内容。可以根据是否需要向服务器重新发起HTTP请求,将缓存过程分为两个部分,分别是强制缓存协商缓存

好处

  • 提高静态资源的加载速度
  • 提高页面渲染速度(取决于资源加载速度)

2. 缓存过程分析

  • 当浏览器首次向服务器发起请求,获取到请求结果;
  • 根据响应报文中HTTP头的缓存标识判断,是否进行缓存资源;
  • 如果存在缓存标识,则将缓存标识和请求结果存入浏览器缓存;
  • 再次发起同个请求时,先从浏览器缓存查找缓存标识和请求结果;
  • 根据缓存标识判断,是否向服务器发起请求,若缓存标识未过期,直接使用浏览器缓存结果;
  • 否则需要向服务器验证,则根据服务器返回结果,判断使用浏览器缓存的请求结果,还是使用服务器返回的新请求结果。
  • 如果服务器返回了新的请求结果,重新将缓存标识和请求结果存入浏览器缓存。
浏览器缓存过程

二、强制缓存

1. 字段说明

Expires

Expires指定资源过期的GMT绝对时间,绝对值,如果客户端的当前时间不超过该时间,则直接使用缓存。此字段是HTTP/1.0控制网页缓存的字段。


比如 0, 代表着过去的日期,即该资源已经过期。

现在浏览器默认使用的是HTTP/1.1,那么expires还能用吗?
可了解HTTP消息

其实,在HTTP/1.1中使用了Cache-Control代替,因为Expires用客户端时间和服务器返回的时间进行比较,但是如果客户端和服务器位于不同时区,造成误差,那么强制缓存则直接失效了。而Cache-Control是通过设置几秒后失效,这种方式相比Expires更可靠些。

Cache-Control

Cache-Control表示控制缓存的策略,其常用属性如下(具体参考Cache-Control):

  • public:所有内容都将被缓存(客户端和代理服务器都可缓存)
  • private:所有内容只有客户端可以缓存,Cache-Control的默认取值
  • no-cache:客户端缓存内容,但是是否使用缓存则需要经过协商缓存来验证决定
  • no-store:所有内容都不会被缓存,即不使用强制缓存,也不使用协商缓存
  • max-age=xxx:缓存内容将在xxx秒后失效,相对值

Cache-Control优先级比Expires高,所以两者同时存在时,只有Cache-Control生效。

2. 三种强制缓存情况

  • 不存在缓存结果和缓存标识,强制缓存失效,直接向服务器发起请求(相当于第一次发起请求)。
  • 存在缓存结果和缓存标识,但已失效,强制缓存失效,则使用协商缓存(下面将具体介绍)。
  • 存在缓存结果和缓存标识,但未失效,则使用强制缓存。


三、协商缓存

当浏览器准备第二次请求资源,如果浏览器中已经存在缓存结果和缓存标识,经过浏览器验证已失效,则会向服务器发送请求,服务器会根据请求头中的信息再次验证是否可以使用缓存。
如果验证通过,则返回HTTP状态码304,告诉浏览器资源未更新,可使用本地的缓存。否则,返回HTTP状态码200,及最新的资源内容和缓存标识。

1. 缓存情况

304使用缓存


200使用新资源


2. 字段说明

Last-Modified / If-Modified-Since

Last-Modified是服务器响应请求时,返回该资源文件在服务器最后被修改的时间,Response Headers响应头信息中

If-Modified-Since是客户端再次发起该请求时,携带上次请求返回的Last-Modified值,通过此字段值告诉服务器该资源上次请求返回的最后被修改时间。Request Headers请求头信息中

服务器收到该请求,发现请求头含有If-Modified-Since字段,则会根据If-Modified-Since的字段值与该资源在服务器的最后被修改时间做对比。
若服务器的资源最后被修改时间大于If-Modified-Since的字段值,则重新返回资源,状态码为200;否则返回304,代表资源无更新,可继续使用缓存文件。

不足:

  • 内容没有变化,但是修改日期发生变化(如周期性重写);
  • 内容变化不重要,不需要所有的缓存数据都重写入新数据(如对拼写和注释修改);
  • 服务器无法准确判断资源的最后修改日期(如动态生成的页面);
  • 资源在毫秒级时间内发生变化(If-Modified-Since只能精确到秒);
Etag / If-None-Match

Etag是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成),资源被修改后,Etag也会随之发生变化。Etag一般是由文件内容hash生成的,也可由文件描述符、修改时间、大小生成。Response Headers响应头信息中
其中,Etag有强弱验证器之分。只要内容发生了变化,强验证器就会变化。HTTP/1.1支持弱验证器,如果只对内容进行了少量修改 ,就允许服务器声明该Etag未变化。服务器用前缀W/来标识Etag为弱验证器。

If-None-Match是客户端再次发起该请求时,携带上次请求返回的唯一标识Etag值,通过此字段值告诉服务器该资源上次请求返回的唯一标识值。Request Headers请求头信息中

服务器收到该请求后,发现该请求头中含有If-None-Match,则会根据If-None-Match的字段值与该资源在服务器的Etag值做对比,一致则返回304,代表资源无更新,继续使用缓存文件;不一致则重新返回资源文件,状态码为200

Etag / If-None-Match优先级比Last-Modified / If-Modified-Since高,所以两者同时存在时,只有Etag / If-None-Match生效。

3. 协商缓存和强制缓存的关系

强制缓存优先于协商缓存进行,若强制缓存(ExpiresCache-Control)生效则直接使用缓存,若不生效则进行协商缓存(Last-Modified / If-Modified-SinceEtag / If-None-Match),协商缓存由服务器决定是否使用缓存,若协商缓存失效,那么代表该请求的缓存失效,重新获取请求结果,返回200并存入浏览器缓存中;生效则返回304,继续使用缓存。


四、浏览器的存储位置

当打开页面https://open.hand-china.com/dashboard(随便一个网页都可),然后点击刷新,打开控制台可以看到请求数据。从下图可看出,状态码为灰色的请求,表示使用了强制缓存。memory cachedisk cache表示缓存存放的位置。

1. 内存缓存(from memory cache)

from memory cache代表使用内存中的缓存,适合频繁读取的资源。一般存放js文件、图片、字体等。

  • 快速读取:将编译解析后的文件存放进内存,占据进程内存资源,能快速读取。
  • 时效性:进程一关闭,就清空内存。
2. 硬盘缓存(from disk cache)

from disk cache则代表使用的是硬盘中的缓存。硬盘内存,则将缓存写入硬盘文件,读取缓存时需要进行I/O操作,然后重新解析缓存内,读取比内存缓存慢,但容量大、存储时间长。一般存放css文件。
浏览器中,读取缓存的顺序为memory –> disk

3. Service Worker

Service Worker 是运行在浏览器背后的独立线程,一般可以用来实现缓存功能。使用 Service Worker的话,传输协议必须为 HTTPS。因为 Service Worker 中涉及到请求拦截,所以必须使用 HTTPS 协议来保障安全。Service Worker的缓存与浏览器其他内建的缓存机制不同,它可以让我们自由控制缓存哪些文件、如何匹配缓存、如何读取缓存,并且缓存是持续性的

Service Worker 实现缓存功能一般分为三个步骤:

  • 首先需要先注册 Service Worker
  • 然后监听到install事件以后就可以缓存需要的文件
  • 那么在下次用户访问的时候就可以通过拦截请求的方式查询是否存在缓存,存在缓存的话就可以直接读取缓存文件,否则就去请求数据。

Service Worker 没有命中缓存的时候,我们需要去调用 fetch 函数获取数据。也就是说,如果我们没有在 Service Worker 命中缓存的话,会根据缓存查找优先级去查找数据。但是不管我们是从 Memory Cache 中还是从网络请求中获取的数据,浏览器都会显示我们是从 Service Worker中获取的内容。

4. 推送缓存(Push Cache)

Push Cache(推送缓存)是 HTTP/2 中的内容,当以上三种缓存都没有命中时,它才会被使用。它只在会话(Session)中存在,一旦会话结束就被释放,并且缓存时间也很短暂,在Chrome浏览器中只有5分钟左右,同时它也并非严格执行HTTP头中的缓存指令。

有如下一些特性:

  • 所有的资源都能被推送,并且能够被缓存,但是 EdgeSafari 浏览器支持相对比较差。
  • Push Cache 中的缓存只能被使用一次
  • 可以给其他域名推送资源
  • 浏览器可以拒绝接受已经存在的资源推送
  • 一旦连接被关闭,Push Cache 就被释放
  • 可以推送 no-cacheno-store 的资源
  • 多个页面可以使用同一个HTTP/2的连接,也就可以使用同一个Push Cache。这主要还是依赖浏览器的实现而定,出于对性能的考虑,有的浏览器会对相同域名但不同的tab标签使用同一个HTTP连接。

五、缓存相关状态码

  • 200:强制缓存Expires/Cache-Control失效时,返回新的资源文件
  • 200(disk cache/memory cache):强制缓存Expires/Cache-Control两者都存在,未过期,Cache-Control优先Expires时,浏览器从本地获取资源成功。浏览器强制缓存校验通过结果。
  • 304(Not Modified):协商缓存Last-modified/Etag没有过期时,服务端返回状态码304。服务器协商缓存校验通过结果。

六、刷新操作下的缓存资源情况

F5刷新

刷新某个页面,浏览器设置max-age:0,并在请求头中携带缓存资源中的Last-ModifiedEtag,强制跳过浏览器新鲜度检查(即强制缓存的校验),直接发起请求到服务器进行协商校验,服务器验证通过则使用缓存。如下,

请求页面地址

请求头

响应头

ctrl+F5刷新

刷新某个页面,浏览器设置Cache-Control: no-cache,并且不携带缓存资源中的Last-ModifiedEtag,强制跳过浏览器新鲜度检查(即强制缓存的校验),直接发起请求到服务器,服务器没有获取到If-None-MatchIf-Modified-Since,无法命中再验证,则返回200,资源以及缓存信息。

请求页面地址

请求头

响应头

七、选择合适的缓存

  • 请求顺序
    Expires/Cache-Control:请求服务器之前,浏览器进行对比
    Last-Modified / If-Modified-SinceEtag / If-None-Match:请求服务器进行对比
  • 协商缓存配合使用强制缓存。如果不开启强制缓存,协商缓存开启也没什么根本意义。
  • 一般web服务器同时开启协商缓存Last-Modified / If-Modified-SinceEtag / If-None-Match
  • 分布式系统里多台机器间文件的Last-Modified必须保持一致,以免负载均衡到不同机器导致比对失败;
  • 分布式系统尽量关闭掉ETag(每台机器生成的ETag都会不一样);

参考链接
彻底理解浏览器的缓存机
缓存(二)——浏览器缓存机制:强缓存、协商缓存
浏览器的缓存机制

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,122评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,070评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,491评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,636评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,676评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,541评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,292评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,211评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,655评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,846评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,965评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,684评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,295评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,894评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,012评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,126评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,914评论 2 355

推荐阅读更多精彩内容