浏览器缓存问题

你有没有注意到,当你第一次访问一个网站的时候,页面要等好久才能呈现出来,如果是第二次访问这个网站的时候,网页呈现速度远远比第一次访问的时候快很多,这是为什么呢?然而这并不是偶然,这是浏览器缓存的缘故。

浏览器缓存存在的原因

所有的浏览器都试图将网站的静态资源缓存到本地来减少网页的加载时间,减少网络流量。从远程服务器获取资源消耗的时间要远远超过从本地获取资源的时间。

浏览器缓存是如何工作的?

场景一:用户之前没有访问过此网站

浏览器没有缓存此网站的任何信息,所以首次访问时,所有资源都要从远程服务器拉取。


image.png

我们可以看一下浏览器的请求信息

image.png
image.png

场景二: 用户第二次访问该网站

浏览器将从 Web 服务器检索 HTML 页面,但是一些静态资源比如 JavaScript、CSS、图片等会直接从本地缓存中获取。


image.png

这时我们刷新页面发现,请求时间明显少了很多。


image.png

我们可以点击一个静态的 CSS 文件看一下他的请求头,发现他是从本地缓存获取的。


image.png

浏览器是如何知道要缓存什么呢?

浏览器会侦查服务器端 HTTP 返回的头部信息,头部信息中有四个因素决定缓存问题。

  • ETag
  • Cache-Control
  • Expires
  • Last-Modified

ETag

ETag(或实体标签)是一个字符串,用作缓存验证。
服务器可以在其响应中包括ETag,然后浏览器可以在将来的请求(在文件过期之后)中使用ETag来确定缓存是否包含过期的副本。

如果值是相同的,那么资源没有改变,服务器用304响应代码(未修改)响应,主体是空的。这使浏览器知道使用缓存的副本仍然是安全的。


image.png

注意,只有当文件在缓存中过期时,才在请求中使用ETag。

Cache-Control

Cache-Control报头有许多我们可以设置的指令来控制缓存,如缓存行为、过期和验证。这些也可以结合在一起。

Cache Behavior
Cache-Control: public

public意味着资源可以通过任何缓存(浏览器、CDN等)进行缓存。

Cache-Control: private

private表示资源只能由浏览器缓存

Cache-Control: no-store

告诉浏览器总是从服务器获取资源

Cache-Control: no-store

这个设置可能有点误导,这并不意味着“不要缓存”。他告诉浏览器、缓存服务器,不管本地副本是否过期,使用资源副本前,一定要到源服务器进行副本有效性校验。

Expiration
Cache-Control: max-age=60

这指定了应该缓存资源的时间长度,所以max-age=60表示应该缓存1分钟。RFC 2616建议最大值不应超过1年(最大年龄=31536000)。

Cache-Control: s-max-age=60

这仅供CDN等中间缓存使用。

Validation
Cache-Control: must-revalidate

告诉浏览器、缓存服务器,本地副本过期前,可以使用本地副本;本地副本一旦过期,必须去源服务器进行有效性校验。

Expires

Expires头来自较旧的HTTP 1.0,但是仍然在许多站点上使用。
这个头部字段提供一个到期日期,在此日期之后,该资源被视为无效。

Expires: Wed, 25 Jul 2018 21:00:00 GMT

如果Cache-Control中有max-age指令,浏览器将忽略该字段

Last-Modified

Last-Modified 也是来自 HTTP1.0

Last-Modified: Mon, 12 Dec 2016 14:45:00 GMT

此字段包含上次修改资源的日期和时间。

HTML Meta Tag

在HTML5之前,使用HTML内部的元标记来指定缓存控制是一种有效的方法

<meta http-equiv="Cache-control" content="no-cache">

现在不鼓励使用,而且这个特性已经被Web 标准移除,之所以现在在一些浏览器中还有效是因为需要一个适应的过程,如果在项目中用到了要及时更新代码。而且这样做只有浏览器才能够解析此标记并理解它,而中间缓存不会。所以推荐使用HTTP头发送缓存指令来进行缓存设置。

HTTP Response

让我们看一个 HTTP 响应的例子

Accept-Ranges: bytes
Cache-Control: max-age=3600
Connection: Keep-Alive
Content-Length: 4361
Content-Type: image/png
Date: Tue, 25 Jul 2017 17:26:16 GMT
ETag: "1109-554221c5c8540"
Expires: Tue, 25 Jul 2017 18:26:16 GMT
Keep-Alive: timeout=5, max=93
Last-Modified: Wed, 12 Jul 2017 17:26:05 GMT
Server: Apache

第二行告诉我们缓存时间是1小时
第五行告诉我们返回的是 png 图片
第七行告诉我们 ETag 的值,这个值将在一小时以后用来校验资源是否被更改过
第八行是过期时间,如果设置了第二行的话,这个设置将被视为无效
第十行告诉我们这个图片最后被编辑的时间

缓存陷阱

由上,我们已经确定浏览器缓存是非常棒的,我们应该合理的利用它。

但是我们希望用户在访问页面时能看到我们网站页面的最新版本。但是我们不能期望他们每次访问我们的站点时都需要进行硬刷新(Ctrl-F5)才行。

假设我们修复了名为app.min.js的JavaScript文件中的一个bug,并将更新推送到生产站点。

<script src="assets/js/app.min.js">

但是缓存的过期时间设置的是一周

Cache-Control: private, max-age=604800

这样有些用户还是会访问原来的app.min.js文件,bug 还是会存在。那我们应该怎么办呢?

缓存破坏

缓存破坏是指我们使缓存的文件无效,并强制浏览器从服务器检索文件。

我们可以通过简单地更改文件名来指示浏览器绕过缓存。对于浏览器来说,这是一个全新的资源,因此它将从服务器获取资源。

缓存破坏还允许我们为可能频繁变化的资源保留较长的最大年龄值。Google建议将最大年龄设置为1岁(来源)

Versioning(版本控制)

我们可以给文件设置一个版本

assets/js/app-v2.min.js

Fingerprinting(指纹)

我们可以根据文件内容给文件名添加指纹信息

assets/js/app-d41d8cd98f00b204e9800998ecf8427e.min.js

添加查询参数

assets/js/app.min.js?version=2

即使在HTTP响应头中添加了 Cache-control:p public ,很多代理服务器不会缓存带有 “?”的资源,所以不推荐此种方法。

最好的选择

推荐:

  • 使用Cache-Control and ETag控制缓存行为来处理静态资源
  • 设置长的最大年龄值,并使用指纹或版本控制来破坏缓存机制

不推荐:

  • 使用 HTMLmeta 标签来设置缓存行为
  • 使用添加查询参数来破坏缓存机制

如何设置浏览器不缓存呢?

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

对学习抱有热情的开发小伙伴欢迎加入 qq群685421881,更欢迎热爱编程的妹子进入,让我们一起学习 并进步吧!

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

推荐阅读更多精彩内容

  • 浏览器对于请求资源, 流程如图所示: 可以看到浏览器的缓存机制分为两个部分: 1、当前缓存是否过期? 2、服务器中...
    zhoulujun阅读 1,206评论 0 3
  • 网络特有的延迟以及数据传输的成本,制约互联网快速获取Web资源。为此,HTTP协议引入缓存以空间换时间,使浏览器缓...
    大头8086阅读 3,068评论 2 12
  • 最近上线发现,新上线的内容要强刷下浏览器,页面才会是新内容 Last-Modified 是什么 Last-Modi...
    橙子Alisa阅读 382评论 0 0
  • 对于浏览器缓存,相信很多开发者对它真的是又爱又恨。一方面极大地提升了用户体验,而另一方面有时会因为读取了缓存而展示...
    l鹿狸i阅读 745评论 0 5
  • 蝶恋花 昨夜蛩声催玉漏,残影扶疏,宛若秋思透。冷酒未消人忆旧,犹怜萍聚终须散。 碎念琴箫约白首,多少欣悲,却被相...
    明月劫阅读 134评论 0 3