浏览器如何处理多次引用的不可缓存资源?

时间:2013-05-02 08:53:56

标签: html http caching browser browser-cache

This雅虎开发者网络文章称,浏览器处理在一个HTML中不同引用的不可缓存资源。我在HTTP/1.1 cache RFC中找不到任何关于此的规则。

我在Chrome中做了一些实验,但我无法弄清楚确切的规则。它只加载了一次重复的非可缓存脚本标记。然后我在3个iframe中引用了相同的脚本。第一个触发了网络请求,但其他的则是从缓存中提供的。我试图引用与图像的src相同的url,并再次触发网络请求。

是否有关于此行为的文档?浏览器之间有何不同?

2 个答案:

答案 0 :(得分:3)

当客户端决定检索资源时,它是RFC2616,它管理是否可以从缓存中返回该资源的规则,或者需要从源服务器重新验证/重新加载(主要是{{3}但你真的需要读完整个事情。)

但是,当您在同一页面上拥有相同资源的多个副本时,在按照RFC2616的规则检索到第一个副本之后,HTML5规范现在将决定是否检索其他副本(主要是在section 14.9)中指定。

特别注意步骤10:

  

如果由于其他原因(例如,此算法的另一次调用)已经下载了资源[...],并且此请求将与前一个请求相同(例如,相同的Accept和Origin标头),并且用户代理配置为重用现有下载中的数据而不是启动新数据,然后使用现有下载的结果而不是开始新的下载。

这清楚地描述了在决定资源是否可以重复使用时可能发挥作用的一些因素。一些关键点:

  • 相同的Accept和Origin标头:虽然大多数浏览器在任何地方都使用相同的Accept标头,但在Internet Explorer中,图像与脚本与HTML不同。当涉及到框架时,每个浏览器都会发送不同的Referer,虽然未直接提及Referer,但AcceptOrigin仅作为示例提供。

  • 已下载:请注意,这与已下载有很大不同。因此,如果资源在页面上多次出现,但第一次出现在遇到第二次出现之前已完成下载,则重用选项可能不适用。

  • 用户代理配置为重用数据:这对我来说意味着重用或重新检索数据的决定在某种程度上由用户代理决定,或者至少是用户选项。

最终结果是,每个浏览器处理缓存的方式略有不同。即使在特定的浏览器中,结果也可能因时间而异。

我创建了一个包含三个嵌套框架的测试用例(即包含iframe的页面,其本身包含iframe)和相同脚本的6个副本,每页2个(使用{{ 1}}使它们不可缓存,但也使用其他变体进行测试,包括Cache-Control:no-cache)。

  • Chrome仅加载了1份。
  • Internet Explorer倾向于变化,假定基于负载,但介于1和3之间。
  • Safari加载了3个副本,每个帧一个(即具有不同的max-age=0标题)。
  • Opera和Firefox加载了所有6份。

当我在几个图像中重复使用相同的资源(一个在根页面上,一个在第一个Referer中)并且其他一些图像供参考时,行为也发生了变化。

  • Chrome现在加载了5个副本,每个页面上每种类型1个。虽然Chrome中的iframe标题对于图片和脚本来说是相同的,但标题顺序却不同,这表明它们可能会有不同的处理方式,并且可能会以不同方式缓存。
  • Internet Explorer加载了2个副本,每个类型中有1个是预期的副本。假设它们可能有所不同,因为它们只是脚本时的行为。
  • Safari仍然只有3个副本,每帧一个。
  • Opera仍然莫名其妙地6.不知道那些部分是脚本,哪些是图像。但可能这也可能因负载或时间而异。
  • Firefox加载了8份副本,这对他们来说是预料之中的。 6个脚本,加上2个新图像。

现在这是正常查看页面时发生的事情 - 即只是将页面URL输入地址栏。使用F5强制重新加载(或Safari上的任何等效项)会产生完全不同的结果集。一般来说,重新加载的整个概念,F5 vs Ctrl-F5,客户端发送的标题等等也从一个浏览器到下一个浏览器有很大不同。但这是另一天的主题。

底线是缓存从一个浏览器到另一个浏览器是非常不可预测的,并且规范有点让实现者决定什么对他们最有效。

我希望这已经回答了你的问题。

附加说明我应该提一下,我并没有竭尽全力测试每个浏览器的最新版本(Safari特别是古老的v4,Internet Explorer是v9,但是其他人可能是最新的)。我怀疑它有多大区别。所有浏览器在这方面突然收敛于一致行为的可能性极小。

答案 1 :(得分:1)

Molnarg,如果你正确阅读这篇文章,就会明白为什么会这样。

  

不必要的HTTP请求在Internet Explorer中发生,但不在   Firefox浏览器。在Internet Explorer中,如果包含两次外部脚本   并且不可缓存,它在页面期间生成两个HTTP请求   加载。即使脚本是可缓存的,也会发生额外的HTTP请求   当用户重新加载页面时。

此行为仅适用于Internet Explorer。如果你问我为什么会这样,我会说IE开发人员选择忽略HTTP/1.1 cache RFC或者至少无法实现它。也许这是一项正在进行的工作。但是又有很多方面,其中IE与大多数浏览器(JavaScript,HTML5,CSS)不同。除非开发者更新它,否则这无济于事。

雅虎开发文章你gave列出了高性能的最佳实践。这必须适应所有受此影响的IE用户。这就是为什么多次包含相同的脚本,虽然其他浏览器可以伤害IE用户,应该避免使用。

更新

非可缓存资源将生成一次或多次网络请求。

来自 2。来自HTTP/1.1 cache RFC

的缓存操作概述
  

虽然缓存是HTTP的完全可选功能,但我们假设   重用缓存的响应是可取的,并且这种重用   是没有要求或本地需要时的默认行为   配置阻止它。

因此,使用缓存意味着尝试重用和非缓存意味着相反。可以把它想象成这个不可缓存的请求就像关闭缓存的HTTP请求(从带有缓存的HTTP回退)。

Cache-Control:max-age = n不会阻止缓存存储它只是说明缓存项在n秒后失效。要防止使用缓存,请将这些标头用于图像:

Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: 0