caching - 停止浏览器以发出应保留在缓存中的图像的HTTP请求-mod_expires

Translate

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

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

值得庆幸的是,服务器响应似乎是正确的:

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 

好吧,我认为这将停止浏览器下载,甚至会向服务器询问有关图像的1年时间。但这是部分正确的:原因如果关闭并重新打开浏览器,则浏览器不会下载图像从服务器上,但是浏览器仍然向服务器查询每个图像的HTTP请求.

如何强制浏览器停止为每个图像发出HTTP请求?即使这些HTTP请求后面没有下载映像,它们仍然是对服务器的请求不必要地增加延迟并减慢页面渲染速度!

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


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

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

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

  • 当我关闭浏览器并在同一页面上再次打开它时,愚蠢的浏览器每张图像都会向服务器发出一次HTTP请求:它不会降级图像,但仍会发出HTTP请求,就像浏览器在查询关于图像的服务器(服务器回复200 OK)。这是激怒我的!

如果您感兴趣,我还会附上以下图表:

enter image description here

enter image description here

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

EDIT2:并删除Last-Modified标头提示这里,不能解决问题,没有任何区别。

This question and all comments follow the "Attribution Required."

所有的回答

Translate

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

我会推荐真正有用的Firefox插件实时HTTP标头这样您就可以看到网络上到底发生了什么。

而且可以肯定的是,您可以ssh / putty服务器并执行类似的操作

tail -f /var/log/apache2/access.log
来源
Translate

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

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

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

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

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

这就是为什么您无法做很多事情来阻止浏览器发送针对缓存页面元素的HTTP请求。

但是,如果您查看html5随附的其他可用的客户端解决方案,则可以防止资源加载

  1. 缓存清单(尽管有陷阱)
  2. 索引数据库(不错的异步功能,允许Blob存储)
  3. 本地存储(不是异步的)
来源
Translate

“重新加载”和“刷新”之间有区别。仅浏览带有后退和前进按钮的页面通常不会启动新的HTTP请求,但是特别是按F5键“刷新”页面将导致浏览器再次检查其缓存。这取决于浏览器,但似乎是FF和Chrome的规范(即能够轻松监视其网络流量的浏览器。)击中F6,Enter应将URL地址栏聚焦,然后“转到”它,应该重新加载页面,但不要再次检查页面上的资产。

更新资料:阐明前后导航行为。它称为“后退缓存”或高速缓存在浏览器中。使用后退/前进按钮导航时,其目的是向您显示与在自己的时间轴中看到的页面完全相同的页面。即使使用服务器高速缓存头表明特定项目已过期,使用来回转发时也不会发出服务器请求。

如果在开发人员网络面板中看到(200 OK BFCache),则服务器从未被命中-甚至询问是否已修改。

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

来源
Translate

如果我使用F5或F5 + Ctrl强制刷新,则会发送请求。但是,如果我关闭浏览器并再次输入URL,则不会发送任何要求。我测试是否发送请求的方法是通过在服务器上的开始请求上使用断点,即使未发送请求时,它仍然在Firebug中显示为等待了7毫秒,因此请当心。

来源
Translate

您在此处描述的内容并不反映我的经验。如果内容是通过no-store指令提供的,或者您进行了明确的刷新,那么可以,我希望它可以返回到原始服务器,否则应该在浏览器重新启动时将其缓存(假设允许并可以写入)缓存文件)。

更加详细地查看瀑布(这很棘手,因为它们有点小且模糊),浏览器似乎在做应有的工作-它具有图像的条目-但这些只是加载中从本地缓存而不是来自原始服务器-请检查响应中的“日期”标头(您为什么认为它用的是毫秒而不是秒?)。这就是为什么它们的颜色不同。

来源
Translate

在花费大量时间寻找合理的答案之后,我发现以下链接最有用,并且确实可以回答这里提出的问题。

https://webmasters.stackexchange.com/questions/25342/headers-to-prevent-304-if-modified-since-head-requests

来源
Translate

如果这是生死攸关的问题(如果您想以这种方式优化页面加载,或者无论如何都希望尽可能减少服务器上的负载),那么有一种解决方法。

使用HTML5本地存储在第一次请求图像后缓存图像。

  • [+]您可以阻止浏览器发送HTTP请求,无论用户如何努力(F5,Ctrl + F5,仅重新访问页面等),该请求都将以99%的返回304(未修改)。

  • [-]为此,您必须在JavaScript支持上付出更多的努力。

  • [-]图像存储在base64中(我们不能存储二进制数据),这就是为什么每次在客户端对其进行解码的原因。哪一个通常速度非常快,没什么大不了的,但是在客户端仍然需要额外使用cpu,因此请记住。

  • [-]本地存储空间有限。您可以针对每个域使用约5mb的数据(注意:base64将图像的原始大小增加约30%)。

  • [?]支持者多数浏览器。http://caniuse.com/#search=localstorage

测试

来源
Translate

您在Chrome中看到的不是实际的HTTP请求记录,而是资产请求记录。 Chrome这样做是为了向您显示该页面实际上正在请求资产。但是,此视图实际上并未真正指示是否正在发出请求。如果缓存了资产,Chrome将不会实际创建基础HTTP请求。

您还可以通过将鼠标悬停在时间轴上的紫色部分上来确认这一点。缓存的资源将具有(from cache)在工具提示中。

为了查看实际的HTTP请求,您需要在较低级别上进行查看。在某些浏览器中,这可以通过插件(例如Live HTTP Headers)来完成。

但实际上,要验证请求是否真正发出,您需要检查服务器日志或使用调试代理(例如Charles或Fiddler)。这将在HTTP级别上工作,以确保请求实际上没有发生。

来源
Translate

缓存验证和304响应

在许多情况下,Internet Explorer需要检查缓存的条目是否有效:

  • 缓存的条目没有到期日期,并且在浏览器会话中第一次访问内容

  • 缓存的条目具有到期日期,但已到期

  • 用户已通过单击“刷新”按钮或按F5来请求页面更新

如果缓存的条目具有最后修改日期,则IE将它发送到GET请求消息的If-Modified-Since标头中:

GET /images/logo.gif HTTP/1.1
Accept: */*
Referer: http://www.google.com/
Accept-Encoding: gzip, deflate
If-Modified-Since: Thu, 23 Sep 2004 17:42:04 GMT
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;)
Host: www.google.com

服务器检查If-Modified-Since标头并做出相应的响应。如果自指定的日期/时间以来未更改内容,它将以状态码304和仅包含标题的响应消息进行答复:

HTTP/1.1 304 Not Modified
Content-Type: text/html
Server: GWS/2.1
Content-Length: 0
Date: Thu, 04 Oct 2004 12:00:00 GMT

由于该响应不包含任何内容,并且会导致IE从缓存中读取所需的数据,因此可以快速下载该响应。实际上,这就像重定向到本地浏览器缓存。

如果自If-Modified-Since标头中的日期/时间以来请求的对象实际上已更改,则服务器将以状态码200进行响应并提供资源的修改版本。

来源
Translate

这个问题有更好的答案这里在网站站长堆栈交换站点上。

以上链接中还引用了更多信息,网址为httpwatch

根据这篇文章:

在许多情况下,Internet Explorer需要检查缓存的条目是否有效:

  • 缓存的条目没有到期日期,并且在浏览器会话中第一次访问内容
  • 缓存的条目具有到期日期,但已到期
  • 用户已通过单击“刷新”按钮或按F5来请求页面更新

    在此处输入代码

来源
Leave a Reply
You must be logged in to post a answer.
关于作者