停止浏览器对应该保持缓存的图像发出HTTP请求 - mod_expires

Mar*_*aio 45 browser caching mod-expires http-headers

在这里阅读了很多文章和一些问题后,我终于成功激活了Apache mod_expires,告诉浏览器它必须缓存1年的图像.

<filesMatch "\.(ico|gif|jpg|png)$">
  ExpiresActive On
  ExpiresDefault "access plus 1 year"
  Header append Cache-Control "public"
</filesMatch>
Run Code Online (Sandbox Code Playgroud)

谢天谢地,服务器响应似乎是正确的:

HTTP/1.1 200 OK 
Date: Fri, 06 Apr 2012 19:25:30 GMT 
Server: Apache 
Last-Modified: Tue, 26 Jul 2011 18:50:14 GMT 
Accept-Ranges: bytes 
Content-Length: 24884 
Cache-Control: max-age=31536000, public 
Expires: Sat, 06 Apr 2013 19:25:30 GMT
Connection: close
Content-Type: image/jpeg 
Run Code Online (Sandbox Code Playgroud)

好吧,我认为这会阻止浏览器下载甚至向服务器询问有关图像的信息,为期1年.但部分原因:如果您关闭并重新打开浏览器,浏览器不会再从服务器下载图像,但浏览器仍然会向每个图像发送HTTP请求来询问服务器.

如何强制浏览器停止为每个图像发出HTTP请求?即使这些HTTP请求后面没有下载的图像,它们仍然是向服务器发出的请求,这些请求可能会造成延迟,并减慢页面渲染速度!

我已经告诉浏览器它必须将图像保存在缓存中1年!为什么浏览器仍在为每个图像查询服务器(即使它没有下载图像)?!


查看FireBug中的网络图(菜单FireBug> Net> Images)我可以看到不同的缓存行为(我显然开始使用浏览器缓存完全空,我使用"清除所有历史记录"强制在浏览器上删除缓存):

  • 当第一次加载页面时,所有图像都被下载(如果我通过单击浏览器的重新加载页面按钮强制页面重新加载,则会发生同样的事情).这很有道理!

  • 当我浏览网站并返回同一页面时,根本不会下载图像,浏览器甚至不会向服务器询问任何图像.这是有道理的(我希望在浏览器关闭时也能看到这种行为)!

  • 当我关闭浏览器并在同一页面上再次打开它时,愚蠢的浏览器无论如何都会向服务器发出一次每个图像的HTTP请求:它不会使图像下载,但它仍会发出HTTP请求,就像浏览器查询关于图像的服务器(服务器回复200 OK).这是一个让我烦恼的人!

如果您有兴趣,我也会附上以下图表:

在此输入图像描述

在此输入图像描述

编辑:刚刚使用FireFox 11.0进行测试,以确保它不是我的FireFox 3.6太老的问题.同样的事情发生了!我还测试了谷歌站点和Stackoverflow站点,他们都发送了Cache-Control: max-age=...但是浏览器仍然向服务器发出HTTP请求,一旦浏览器关闭并再次在同一页面上打开,服务器响应后浏览器不会下载图像(正如我上面所解释的那样)但它仍然会发出该死的请求,增加了查看页面的时间.

EDIT2:并Last-Modified按照此处的建议删除标题,但没有解决问题,它没有任何区别.

Jas*_*rel 27

您看到的行为是预期的(请参阅RFC7234以获取更多详细信息),指定的行为:

无论缓存状态如何,所有现代浏览器都会针对显示的每个页面元素向服务器发送HTTP请求.这是根据Web服务(尤其是广告网络)的要求做出的设计决策,以确保HTTP服务器能够维护每个元素的每个显示的记录.

如果浏览器没有发出这些请求,则永远不会通知服务器已向用户显示图像.对于广告网络来说,这将是灾难性的.在早期,广告网络"黑客"他们围绕这种方式,通过使用服务随机生成的名称(例如:"coke_ad_1_98719283719283.gif")相同的广告图像.然而,对于ISP而言,这种做法导致数据传输的大量增加,因为他们的每个用户都在重新下载这些相同的广告图像,绕过他们的ISP正在运行的任何缓存/代理服务器.

因此达成了休战:浏览器总是会发送HTTP请求,即使对于未过期的缓存元素也是如此.服务器将使用HTTP 304状态代码("未修改")进行响应.这允许服务器记录图像显示给客户端的事实.结果,广告网络通常停止使用随机化图像名称来绕过网络缓存服务器.

这为广告网络提供了他们想要的东西 - 显示每个图像的记录 - 并且它为ISP提供了他们想要的东西 - 可缓存的图像和静态内容.

这就是为什么你无法阻止浏览器发送缓存页面元素的HTTP请求的原因.

但是如果你看一下html5附带的其他可用的客户端解决方案,就有一个阻止资源加载的范围

  1. 缓存清单(尽管它有问题)
  2. IndexedDB(很好的异步功能,允许blob存储)
  3. 本地存储(非异步)

  • -1:这是完全错误的.使用正确的缓存控制头**发送的图像将不会被现代浏览器重新请求,直到缓存到期时间,但有一些例外,例如用户强制重新加载页面.通过告知浏览器不缓存图像,广告问题也很容易解决. (16认同)
  • 为了回应@romkyns的说法,除非谷歌和许多其他开发人员对使用服务器重写和版本号以防止服务器命中是错误的,否则这个答案是不正确的. (5认同)
  • 为什么有35人支持这种完全且易于测试的废话?*叹* (4认同)
  • 杰森,你对其他信息有什么参考吗? - 这非常有趣,我正在寻找这样的东西. (3认同)

小智 14

您使用错误的工具来分析请求.

我推荐真正有用的Firefox插件Live HTTP标头,这样你就可以看到网络上真正发生了什么.

而且可以肯定的是,你可以ssh/putty你的服务器并做类似的事情

tail -f /var/log/apache2/access.log
Run Code Online (Sandbox Code Playgroud)


chu*_*die 12

"重新加载"和"刷新"之间存在差异.导航到具有后退和前进按钮的页面通常不会发起新的HTTP请求,但是专门按F5"刷新"页面将导致浏览器仔细检查其缓存.这取决于浏览器,但似乎是FF和Chrome的标准(即能够轻松查看其网络流量的浏览器.)点击F6,输入应该关注URL地址栏然后"转到"它,这应该重新加载页面,但不要仔细检查页面上的资产.

更新:澄清后退和前进导航行为.它在浏览器中称为"后向缓存"或BFCache.当您使用后退/前进按钮导航时,目的是显示您在自己的时间轴中看到的页面.使用后退和前进时不会发出任何服务器请求,即使服务器缓存标头表示特定项目已过期.

如果您在开发人员网络面板中看到(200 OK BFCache),那么服务器从未被命中 - 甚至要求if-modified-since.

http://www.softwareishard.com/blog/firebug/firebug-tip-what-the-heck-is-bfcache/


Pet*_*sby 7

如果我使用F5或F5 + Ctrl强制刷新,则发送请求.但是,如果我关闭浏览器并再次输入url,则会发送NO reqeust.我测试是否发送请求的方式是在服务器上的开始请求上使用断点,即使请求没有发送它仍然在Firebug中显示为已经完成了7毫秒的等待,所以要小心这一点.

  • 它实际上对我有用!如果我使用F5或F5 + Ctrl强制刷新,则发送请求.但是,如果我关闭浏览器并再次输入url,则会发送NO reqeust.我测试是否发送请求的方式是在服务器上的开始请求上使用断点,即使请求没有发送它仍然在Firebug中显示为已经完成了7毫秒的等待,所以要小心这一点. (2认同)

sym*_*ean 6

你在这里描述的内容并不反映我的经验.如果内容是使用no-store指令提供的,或者你进行了明确的刷新,那么是的,我希望它能回到原始服务器,否则它应该在浏览器重启时缓存(假设它被允许,并且可以写缓存文件).

更详细地看一下您的瀑布(这很棘手,因为它们有点小而且模糊)浏览器似乎正在做它应该做的事情 - 它图像的条目 - 但这些只是从本地缓存加载不是从原始服务器 - 检查响应中的"日期"标题(为什么你认为它需要几毫秒而不是秒?).这就是为什么它们的颜色不同.