41

如果我在一个页面中多次使用同一个图像,每个图像会单独加载,占用带宽和流量,还是只会加载一个,其余嵌入代码将重用图像?

例如,假设我这样做了:

<img src="http://img.to/image.jpg"/>
<img src="http://img.to/image.jpg"/>
<img src="http://img.to/image.jpg"/>
<img src="http://img.to/image.jpg"/>
<img src="http://img.to/image.jpg"/>
<img src="http://img.to/image.jpg"/>
...
<img src="http://img.to/image.jpg"/>
<img src="http://img.to/image.jpg"/>

并且image.jpg是100kb。当浏览器加载这个页面时,会浪费掉(100Kb * # of img tags)的流量吗?还是只加载一个image.jpg并将其重用于其余标签?

4

3 回答 3

24

实现第 5 版 HTML 规范的浏览器可以重用图像,而不管缓存相关的 HTTP 标头如何。可能只会发生单个网络请求。

规范定义了图像键。

7.2 让 key 是一个元组,由生成的绝对 URL、img 元素的 crossorigin 属性的模式组成,如果该模式不是 No CORS,则为 Document 对象的来源。

当浏览器下载第一个图像源时,它会使用键将其添加到可用图像列表中。

如果下载成功并且用户代理能够确定图像的宽度和高度

  1. 将 img 元素设置为完全可用状态。
  2. 使用 key 键将图像添加到可用图像列表中。

当浏览器看到另一个具有相同键的图像时,它将从可用图像列表中获取它。

7.3 如果可用图像列表包含键条目,则将 img 元素设置为完全可用状态,适当更新图像的呈现,排队一个任务以在 img 元素上触发一个名为 load 的简单事件,然后中止这些脚步。

尽管如此,浏览器可能会随时从可用图像列表中删除图像。

每个 Document 对象都必须有一个可用图像列表。此列表中的每个图像都由一个元组标识,该元组包含一个绝对 URL、一个 CORS 设置属性模式,如果模式不是无 CORS,则还有一个原点。用户代理可以随时将一个 Document 对象的可用图像列表中的条目复制到另一个(例如,当创建 Document 时,用户代理可以将其他 Document 中加载的所有图像添加到其中),但不得更改这样做时以这种方式复制的条目。用户代理也可以随时从这些列表中删除图像(例如,为了节省内存)。

有关更多信息,请参阅在解析具有多个具有相同 src 的 img 节点的文档时如何使用可用图像列表?GitHub 上的 HTML 标准存储库中的问题。

于 2017-01-13T13:51:26.583 回答
18

试试看——在研究缓存问题时,像 Firebug for Firefox 或 Chrome 中的开发者工具这样的工具非常有用。如果您在其中打开“网络”面板并重新加载页面,您将看到为每个项目发送的 HTTP 状态代码。304(未修改)表示该项目是从缓存中本地检索的。

正如dthorpe上面所说,缓存标头在这里很重要。除了确保没有设置“无缓存”之外,如果您有权访问您的服务器配置,您应该积极主动——如果您知道资源不会改变,您应该确保设置任何一个'Expires' 标头(告诉浏览器缓存副本应被视为陈旧的日期)或 'Cache-Control: max-age' 标头(给出天数/小时数而不是设定日期)。

您也可以为不同的 mime 类型/文件夹设置不同的时间尺度,这允许您获取客户端数据以经常刷新 HTML 内容,但很少刷新图像和样式表。

这是 Google 的精彩介绍视频/文章,值得一看。

于 2012-07-01T18:40:36.507 回答
8

它可能取决于特定的浏览器实现,但我希望对图像的第一次引用会命中服务器,随后对同一图像 URL 的引用将从浏览器缓存中提供。因此,对图像只有一个网络请求。

也就是说,如果服务器在图像响应上设置的 HTTP 缓存标头完全允许浏览器缓存图像。如果缓存标头设置为“no-cache”之类的内容,则浏览器需要为每个引用重新获取图像。您可以使用 Fiddler 等网络数据包嗅探器检查图像响应上的 HTTP 标头。

如果浏览器直到图像完全下载后才在浏览器缓存中填充图像 URL,那么您可能会看到对同一图像的多个请求,但这似乎不太可能。

于 2012-06-30T04:57:06.050 回答