如果路径中有查询字符串,Firefox 是否会缓存 javascript 并在没有请求的情况下使用它?
我想要做的是在 javascript 路径末尾附加一个查询字符串,以便每当我的应用程序更新到新版本时,都会下载 javascript。然而,只要查询字符串相同,我希望它继续使用缓存版本,而不需要执行 http 请求来检查脚本是否已更改。
我在 PHP 中完成此操作的方法是从 CVS 标记中读取。当我构建要输出的 HTML 时,我读取 CVS 标记并使用它附加到 javascript 路径的末尾,以便它创建一个如下所示的脚本标记:
<script src="javascript/messages/shipments.js?TPRSAPPS-DEV2_090828145712237-BRANCH" type="text/javascript"></script>
只要应用程序没有更改,标记将保持不变,因此查询字符串也将保持不变。浏览器应该缓存 JS 并且根本不进行网络请求,因为过期日期是遥远的未来。每次更新应用程序时,该查询字符串都会更改,浏览器应该下载它。
这在 IE8 中效果很好。我的问题是火狐浏览器的问题。 Firefox 缓存了这些文件,但下次加载页面时 Firebug 显示了 304 响应,表明它仍然对该文件进行了网络请求,然后发现它没有更改。
所以我的问题是,当存在查询字符串时,firefox是否会忽略javascript的过期标头和缓存?
相关:Firefox 决定不缓存什么? 显然 Rails 也做了类似的事情。但这并不能回答我的问题。
以下是我对此文件的回复:
https://appdev.prsx.net/~jhargett/PRSApps-Motorlog/javascript/menuReader.js?TPRSAPPS-DEV2_090828145712237-BRANCH-DIFFERENT
HTTP/1.1 304 Not Modified
Date: Mon, 03 Oct 2011 18:35:26 GMT
Server: Apache/2.2.3 (Red Hat)
Connection: close
Etag: "179010-3f8-49a9a74334200"
Vary: Accept-Encoding
Firebug 中的“缓存”选项卡显示:
Last Modified Mon Oct 03 2011 13:35:26 GMT-0500 (Central Daylight Time)
Last Fetched Mon Oct 03 2011 13:35:26 GMT-0500 (Central Daylight Time)
Expires Fri Oct 28 2011 18:33:31 GMT-0500 (Central Daylight Time)
Data Size 345
Fetch Count 12
Device disk
What I would like to do is append a query string on the end of the javascript path so that whenever my application is updated to a new version, the javascript is downloaded. As long as the query string is the same however, I want it to keep using the cached version without doing a http request to check to see if the script has changed.
The way I am accomplishing this in PHP is to read from the CVS tag. When I am building the HTML to output, I read the CVS tag and use that to append to the end of the javascript path so that it creates a script tag that looks like this:
<script src="javascript/messages/shipments.js?TPRSAPPS-DEV2_090828145712237-BRANCH" type="text/javascript"></script>
As long as the app hasn't changed, the tag will stay the same and therefore the query string will also. The browser should cache the JS and not do a network request at all because the expire date is far future. Each time the app is updated, that query string will change and the browser should download it.
This works great in IE8. My problem is with Firefox. Firefox caches the files, but the next time I load the page Firebug shows a 304 response, indicating that it still did a network request for the file and then found that it hadn't changed.
So my question is, does firefox ignore the expires header and cache of javascript when there is a query string?
Related: what does firefox decide not to cache?
Apparently Rails does something similar. But this doesn't answer my question.
Here is the response I am getting back on this file:
https://appdev.prsx.net/~jhargett/PRSApps-Motorlog/javascript/menuReader.js?TPRSAPPS-DEV2_090828145712237-BRANCH-DIFFERENT
HTTP/1.1 304 Not Modified
Date: Mon, 03 Oct 2011 18:35:26 GMT
Server: Apache/2.2.3 (Red Hat)
Connection: close
Etag: "179010-3f8-49a9a74334200"
Vary: Accept-Encoding
The Cache tab in Firebug says:
Last Modified Mon Oct 03 2011 13:35:26 GMT-0500 (Central Daylight Time)
Last Fetched Mon Oct 03 2011 13:35:26 GMT-0500 (Central Daylight Time)
Expires Fri Oct 28 2011 18:33:31 GMT-0500 (Central Daylight Time)
Data Size 345
Fetch Count 12
Device disk
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Firefox 用于决定是否在给定缓存响应的情况下进行条件 GET 的逻辑如下所示:
no-store 或者如果过期时间早于响应日期,则重新验证。
因此,对于您的情况,假设您实际上在 200 响应中设置了过期或最大年龄信息,则不应有条件 GET。
也就是说,一些尝试跟踪 Firefox HTTP 信息的工具实际上会影响重新验证行为,因此您可能会遇到这种情况。
我建议按照 https://developer.mozilla.org/en/HTTP_Logging 如果您能找到日志的正确部分(搜索“nsHttpChannel::CheckCache Enter”以获取实现上述逻辑的函数的日志记录),它会顺便告诉您为什么要执行条件 GET。
The logic Firefox uses to decide whether to make a conditional GET given a cached response is like so:
no-store or if the expiration time is before the Date of the response, revalidate.
So for your case, there should not be a conditional GET, assuming you actually set expires or max-age information on your 200 response.
That said, some of the tools that try to trace HTTP information for Firefox actually affect the revalidation behavior, so you may be running into that.
I recommend creating a log following the steps in https://developer.mozilla.org/en/HTTP_Logging which will incidentally tell you exactly why a conditional GET is being done, if you can find the right part of the log (search for "nsHttpChannel::CheckCache enter" for the logging from the function that implements the above logic).
您看到的内容与实际下载的文件不同,然后说它没有改变。
Firefox 确实通过 HTTP 请求来获取文件信息,而不是文件本身。这实际上意味着 Firefox 的做法比 IE 更聪明。
Firefox 所做的请求只有几个字节大(文件大小、日期等)。所以无论名称是什么,Firefox 都会缓存它(除非禁用)。如果文件本身发生更改,Firefox 会决定重新下载该文件。
你所指出的实际上是正确的行为。
What you are looking at is something different than actually downloading the file, and then say it has not changed.
Firefox does do a HTTP request to get the file information, not the file itself. This actually means firefox is doing this smarter then IE is doing.
The request firefox does is just a couple of bytes large (filesize, date etc). so no matter what the name, firefox caches it (unless disabled). If the file itself changes, firefox decides to re-download the file.
The thing you are pointing out is actually correct behavior.
如果您想绝对确定您的文件将被重新加载,最好将版本号/缓存破坏程序字符串直接放在文件名中。因此,您将拥有类似
shipments_v2.js
或shipments_(unix_timestamp).js
的内容。这将处理代理和任何其他类型的缓存机制。If you want to be absolutely sure that your file will get reloaded, it's better to put the version number/cache buster string directly in the file name. So you'd have something like
shipments_v2.js
orshipments_(unix_timestamp).js
. This will take care of proxies and any other kind of caching mechanisms.正如鲍里斯的回答所解释的,触发条件请求的条件之一是存在 Vary 标头。您通常不想删除 Accept-Encoding 上的变化,但是当您有 URL 版本控制时,您可以做的以及最好做的事情是让浏览器没有任何可重新验证的内容。在你的例子中它是 Etag 标头。它也可以是 Last-Modified 标头。
清漆为您执行此操作的示例代码可能如下所示:
As explained in Boris' answer, one of conditions that trigger conditional request is presence of Vary header. You usually don't want to remove vary on Accept-Encoding, but what you can do and what is good thing to do in case when you have URL versioning, is to leave the browser with nothing to revalidate against. In your case it's Etag header. It can as well be Last-Modified header.
Example code for varnish to do that for you may look like this: