前端缓存机制

最近在做项目,测试同学,客户总是刷新刷不到最新的页面,需要按着Ctrl+F5才能看到最新的页面。之前知道304的概念,去看了测试同学的电脑上面有的是304,有的是内存缓存,有的是磁盘缓存。顺着这个去深入研究了一下。这里可以分为强缓存和协商缓存。


image.png

盗了一张图


image.png

浏览器第一次打开网页的获取资源后,根据返回的响应头信息告诉客户端应该如何做缓存。

一、304资源离线缓存

1. 关于Last-Modified

浏览器第一次请求到页面的时候,服务器返回状态200,资源相应头里面有一个Last-Modified的属性标识,意味着这个文件在服务器端最后一次修改时间。其次还有一个叫做Etag的,他们格式如下
image.png

Last-Modified这里是一个GMT的时间标准和我们的北京时间相差8小时
客户端第二次请求此URL时,根据 HTTP 协议的规定,浏览器会向服务器传送 If-Modified-Since和If-None-Match(可选报头,值Etag的值) 报头,询问该时间之后文件是否有被修改过


image.png

如果服务器端的资源没有变化,则自动返回 HTTP 304 (Not Changed.)状态码,内容为空,否则重新发起请求,请求下载资源这样就节省了传输数据量。当服务器端代码发生改变或者重启服务器时,则重新发出资源,返回和第一次请求时类似。从而保证不向客户端重复发出资源,也保证当服务器有变化时,客户端能够得到最新的资源。
image.png

只有get会被缓存post不会

2. 什么是”Etag”?

HTTP 协议规格说明定义ETag为“被请求变量的实体值” 。 另一种说法是,ETag是一个可以与Web资源关联的记号(token)。典型的Web资源可以一个Web页,但也可能是JSON或XML文档。服务器单独负责判断记号是什么及其含义,并在HTTP响应头中将其传送到客户端,以下是服务器端返回的格式:
  ETag: "50b1c1d4f775c61:df3"
  客户端的查询更新格式是这样的:
  If-None-Match: W/"50b1c1d4f775c61:df3"
  如果ETag没改变,则返回状态304然后不返回,这也和Last-Modified一样。本人测试Etag主要在断点下载时比较有用。
ETag出现的历史原因是Last-Modified只做到了 “秒级别”的验证,无法辨识毫秒,微妙级别的校验,因此才出现了ETag。
ETag的出现,意味着客户端需要需求的升级,因此If-None-Match,If-Match,If-Range随之用来验证文件变化。

3.Last-Modified和Etags可以提高性能

聪明的开发者会把Last-Modified 和ETags请求的http报头一起使用,这样可利用客户端(例如浏览器)的缓存。因为服务器首先产生 Last-Modified/Etag标记,服务器可在稍后使用它来判断页面是否已经被修改。本质上,客户端通过将该记号传回服务器要求服务器验证其(客户端)缓存。
  过程如下:

客户端请求一个页面(A)。

服务器返回页面A,并在给A加上一个Last-Modified/ETag。

客户端展现该页面,并将页面连同Last-Modified/ETag一起缓存。

客户再次请求页面A,并将上次请求时服务器返回的Last-Modified/ETag一起传递给服务器。

服务器检查该Last-Modified或ETag,并判断出该页面自上次客户端请求之后还未被修改,直接返回响应304和一个空的响应体。

此外,如果缓存服务器版本,类型不同,建议使用Last-Modified,Etag可能造成缓存无法验证的问题

二、缓存有效期

HTTP中,通过Cache-Control首部和Expires首部为文档指定了过期时间,通过对过期时间的判断,缓存就可以知道文档是不是在保质期内。Expires首部和Cache-Control:max-age首部都是来告诉缓存文档有没有过期,为什么需要两个响应首部来做这件简单的事情了?其实这一切都是历史原因,Expires首部是HTTP 1.0中提出来的,因为他使用的是绝对日期,如果服务端和客户端时钟不同步的话(实际上这种情况非常常见),缓存可能就会认为文档已经过了保质期。

HTTP 1.1为了修正这个问题,引入了Cache-Control:max-age首部,这个首部使用相对时间来控制保质期,让一切变得更加合理。举个例子,我们买了一瓶汽水,如果使用Expires首部来标注保质期,就会这么写:饮料过期时间:2012年12月21日,如果某个2货不知道今天多少号,他还真不知道这饮料过期没,我小时候饮料都这么写。后来,有个挺有名的卖牛奶的,大概就叫蒙牛,他发明了一种标注保质期的方法,他怎么搞了?他这么写:保质期:12个月,行,牛逼了,我牛奶一年前就生产出来的牛奶,今天要发给厂家,发之前,先往包装上印上生产日期(当然是印发货那天),然后告诉你,明年才过期,这多聪明,搞成相对的,毒死你。也许HTTP 1.1借鉴了这个伟大的发明,于是就有了Cache-Control:max-age首部。

1. Last-Modified&Cache-Control 与 Expire

《1》Last-Modified & Cache-Control
设置 header("Last-Modified: ".gmdate("D, d M Y H:i:s", time() )." GMT");
Last-Modified虽然使用了缓存,但是每次打开页面依然需要向服务器发起http请求,浏览器根据用户的$_SERVER['HTTP_IF_MODIFIED_SINCE']来判断浏览器的内容是否过期,没过期的话返回304状态,浏览器内容从缓存中读取。

此外 Cache-Control也很重要,如果他的值是max-age=0,max-stable,min-refresh等于0或no-store之类的,缓存是不会被缓存的,每次都会请求服务器。如果是max-age,max-stable,min-refresh[大于0]或only-if-cached,immutable,那么很可能出现 from cache现象。

《2》Expires缓存控制
设置 header("Expires: ".gmdate("D, d M Y H:i:s", time()+$cache_time )." GMT");
状态码依然是200,时间依然是旧的时间,Size栏目显示为from cache,表示内容是直接从浏览器读取,浏览器根本就没有向服务器发起http请求。


image.png

image.png

这里有可以分为磁盘缓存和内存缓存区别是
内存中的缓存就是资源存放在内存中,如果浏览器关闭了那么内存中的资源就会被释放,所以它是一个短期缓存,它只会在下一个导航前保存这些缓存,有些情况下可能更短。当访问过页面后,有的数据和资源就会被放入内存中,比如:图片、样式、脚本等。 内存中的缓存读取数据比磁盘快,所以像样式和图片这类的资源会优先使用memory cache,这样读取速度快页面加载就不会容易卡顿。

磁盘缓存就是将资源缓存在磁盘中,相比于内存缓存memory cache磁盘缓存容量就大得多了,但是读取速度会慢一点;所有的资源数据可以缓存,尤其是一些大文件,所以会看到有些脚本文件会存放在内存中,有的会存放在磁盘中,内存容量有限放不下的数据就会存入磁盘中。
磁盘缓存和内存缓存其实都是浏览器强缓存策略的方式,

2. 200 from Cache实现

Status 200 Ok (from cache)出现的条件是Cache-Control或者Expires满足一定的条件。

注意:缓存控制是服务器进行报头建议,以下报头是响应头,不是请求头

2.1 使用 Cache-Control

1.[(max-age|max-stable|min-refresh) = 缓存创建时间 < 当前系统时间][immutable][only-if-cached]
2.缓存必须带有ETag或者Last-Modified
Cache-Control:public,Max-Age=84800
ETag:"f6c01531e9c65fa96f3d40409fd030f1"
image.png

2.2 Expires不能过期

Expires:Sun, 31 Jul 2016 00:19:47 GMT
image.png

以上2种方案只要实现一种即可实现资源from cache

对于浏览器而言,还有一种数据是 DataURL协议的数据,这种数据也会从缓存读取,实现from cache ,但是,如果将所有数据转码成DataURL,会出现性能问题。

三.缓存使用技巧

①. 无论是开发阶段还是生产阶段,建议使用Cache-Control + Last-Modified或Tag控制缓存

②. 开发阶段, 建议使用Cache-Control:[no-cache,no-store|Max-Age=0]这样可以阻止浏览器使用缓存

③ 无论是开发阶段还是生产阶段,如果是永远不会被更改的资源,那么建议使用缓存Cache-Control:[Max-Age=3600][only-if-cached][immutable] 从而实现from cache,减少http请求。

④. 如果是生产阶段建议使用Cache-Control:Max-Age=3600[no-cache|] ,缓存1小时,每次必须到服务器进行校验

⑤. 禁止缓存

Cache-Control: no-cache, no-store, must-revalidate

⑥. 缓存静态资源也可以加上public,实现跨域缓存共享

Cache-Control:public, max-age=31536000

⑦. must-revalidate,校验本地缓存是否过期,过期了才去请求服务器更新缓存

⑧ 默认情况下,Cache-Control:public缓存都回去和服务器校验的

关于 Cache-Control: max-age=秒 和 Expires

Expires = 时间,HTTP 1.0 版本,缓存的载止时间,允许客户端在这个时间之前不去检查(发请求)
max-age = 秒,HTTP 1.1版本,资源在本地缓存多少秒。
如果max-age和Expires同时存在,则被Cache-Control的max-age覆盖。

Expires 的一个缺点就是,返回的到期时间是服务器端的时间,这样存在一个问题,如果客户端的时间与服务器的时间相差很大,那么误差就很大,所以在HTTP 1.1版开始,使用Cache-Control: max-age=秒替代。

Expires =max-age + “每次下载时的当前的request时间”

所以一旦重新下载的页面后,expires就重新计算一次,但last-modified不会变化

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

推荐阅读更多精彩内容