浏览器缓存指南

2021-03-18  本文已影响0人  魂斗驴

概述

缓存是Web浏览器的有用但令人惊讶的复杂功能。

在本文中,我们将说明浏览器如何使用缓存来更快地加载页面,哪些因素决定了缓存的持续时间,以及在必要时如何绕过缓存。

为什么缓存很重要?

所有浏览器都尝试保留静态资产的本地副本,以减少页面加载时间并最大程度地减少网络流量。

通过网络获取无线资源升升总是比从本地缓存中检索它慢。无论服务器位于同一网络上还是位于世界的另一端,都是如此。

浏览器缓存的工作方式

情况1:用户之前没有访问过该站点

浏览器不会为该站点缓存任何文件,因此它将从服务器获取所有内容。

以下是首次访问Wikipedia主页时下载的资源的快照。底部的状态栏显示265KB数据已传输到浏览器。

情况2:用户之前访问过该站点

浏览器将从Web服务器上检索HTML页面,但会在其缓存中查询静态资产(JavaScript,CSS,图像)。

当刷新Wikipedia页面时,我们可以看到缓存的不同之处:

传输的数据减少到928字节-占初始页面加载大小的0.3%。Size列向我们显示了大多数内容都是从缓存中提取的。

Chrome浏览器将从内存缓存或磁盘缓存中提取文件。由于在案例1和案例2之间没有关闭浏览器,因此数据仍在内存缓存中。

查看浏览器缓存

在Chrome中,我们可以转到chrome://cache查看缓存的内容。这将显示指向每个缓存文件的详细视图的链接页面。

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

浏览器检查由Web服务器生成的HTTP响应的标头。通常有四个用于缓存的标头:

ETag

ETag的(或实体标签)是作为一个缓存验证令牌的字符串。这通常是文件内容的哈希。

服务器可以在响应中包含一个ETag,然后浏览器可以在将来的请求中使用该ETag(在文件过期之后),以确定缓存是否包含陈旧的副本。

如果哈希值相同,则说明资源没有更改,服务器将以304响应代码(未修改)作为响应,并带有一个空的正文。这使浏览器知道使用缓存的副本仍然安全。

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

Cache-Control 缓存控制

所述Cache-Control报头具有一个数目,我们可以设置成控制高速缓存行为,过期,和验证指令。这些也可以组合在一起。

public表示该资源可以由任何缓存(浏览器,CDN等)缓存。

私有意味着该资源只能由浏览器缓存

这告诉浏览器总是向服务器请求资源

这实际上有点误导。这并不意味着“不缓存”。

这告诉浏览器缓存文件,但不使用它,直到它与服务器核实我们是否拥有最新版本。该验证是通过ETag标头完成的。

这通常与HTML文件一起使用,因为对于浏览器而言,始终检查最新标记是有意义的。

有效期

这指定了要缓存资源的时间长度(以秒为单位)。因此,max-age = 60表示应将其缓存1分钟。RFC 2616建议的最大值不应超过1年(max-age = 31536000)。

仅由CDN之类的中间缓存使用。

验证

这告诉缓存,缓存必须在使用之前验证过时资源的状态,并且不应使用过期的资源。

过期时间

过期头是从旧的HTTP 1.0天,但仍然在许多网站使用。

该标题字段提供了到期日期,之后该资产被视为无效。

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

最后修改

Last-Modified标头也来自HTTP 1.0天。

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

HTML元标记

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

现在不鼓励使用这样的元标记,并且该标记不是有效的HTML5。为什么?这不是一个好主意,因为只有浏览器才能解析并理解meta标记。中级缓存不会。

因此,请始终通过HTTP标头发送缓存指令。

HTTP响应

让我们看一下示例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

缓存陷阱

因此,我们已经确定浏览器缓存非常棒,我们应该利用它。

但我们也希望用户在进行更新时看到我们页面的最新版本。我们不能期望他们每次访问我们的网站或定期清除其缓存时都进行一次硬刷新(Ctrl-F5)。

这些类型的缓存问题通常使开发人员和最终用户都感到沮丧。用户可能会看到一个破碎的页面或一个行为异常的按钮,因为他们拥有过时的样式表或JavaScript代码。

陈旧文件

以下是Chase Support与银行网站上登录表单有问题的用户之间的Twitter交流。

用户可能在浏览器中缓存了一些旧的JavaScript,这导致重置表单而不是在单击“登录”按钮时提交。

让我们探讨一下陈旧文件可能咬我们的另一种情况。

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

这是我们的HTML:

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

我们的网络服务器将JavaScript文件的最大使用期限设置为1周(604,800秒)。

Cache-Control: private, max-age=604800

更新后,一些用户报告说他们仍然存在该错误的症状。

这里发生了什么?

在下一节中,我们将看到如何使用称为“缓存清除”的技术来防止这些问题。

快取清除

缓存清除是我们使缓存文件无效并强制浏览器从服务器检索文件的地方。

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

缓存清除还使我们可以为可能经常更改的资源保留较长的最大寿命值。Google建议将最大年龄设置为1年(来源)。

版本控制

我们可以在文件名中添加一个版本号:

assets/js/app-v2.min.js

指纹识别

我们可以根据文件内容添加指纹:

assets/js/app-d41d8cd98f00b204e9800998ecf8427e.min.js

追加查询字符串

我们可以在文件名的末尾附加一个查询字符串:

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

查询字符串方法在代理服务器中存在已知问题,因此通常不建议使用此方法。

最佳实践

常问问题

如何判断是否从缓存加载了文件?

在浏览器中检出开发人员工具。在Chrome浏览器中,此信息显示在Size列下的“网络”标签中。

如何防止文件缓存?

使用以下响应标头:

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

参考

A Web Developer’s Guide to Browser Caching

上一篇下一篇

猜你喜欢

热点阅读