简体   繁体   English

如果路径中有查询字符串,Firefox是否会缓存JavaScript并在没有请求的情况下使用它?

[英]Does Firefox cache javascript and use it without a request if there is a querystring in the path?

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. 我想做的是在javascript路径的末尾附加一个查询字符串,以便每当我的应用程序更新到新版本时,都下载javascript。 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. 只要查询字符串是相同的,我希望它继续使用缓存的版本,而无需执行http请求来检查脚本是否已更改。

The way I am accomplishing this in PHP is to read from the CVS tag. 我在PHP中完成此操作的方法是从CVS标记中读取。 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: 当我构建要输出的HTML时,我阅读了CVS标记并将其附加到javascript路径的末尾,以便它创建如下所示的脚本标记:

<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. 浏览器应缓存JS,而根本不发出网络请求,因为到期日期将很远。 Each time the app is updated, that query string will change and the browser should download it. 每次更新应用程序时,该查询字符串都会更改,浏览器应下载该字符串。

This works great in IE8. 这在IE8中效果很好。 My problem is with Firefox. 我的问题是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. Firefox缓存了文件,但是下次加载页面时,Firebug会显示304响应,表明它仍然对文件进行了网络请求,然后发现它没有更改。

So my question is, does firefox ignore the expires header and cache of javascript when there is a query string? 所以我的问题是,当有查询字符串时,firefox是否会忽略expires标头和javascript的缓存?

Related: what does firefox decide not to cache? 相关: firefox决定不缓存什么? Apparently Rails does something similar. 显然,Rails做类似的事情。 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: 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

The logic Firefox uses to decide whether to make a conditional GET given a cached response is like so: 在给定缓存的响应的情况下,Firefox用来决定是否进行条件GET的逻辑如下:

  1. If there is a relevant Vary header, revalidate. 如果存在相关的Vary标头,请重新验证。
  2. If this request is supposed to be force-loaded from cache, do not revalidate. 如果应该从缓存强制加载此请求,请不要重新验证。
  3. If this request has the "always validate" flag, revalidate. 如果此请求具有“始终验证”标志,请重新验证。
  4. If this request has the "never validate" flag then revalidate only if this is a no-store response or SSL no-cache response. 如果此请求具有“从不验证”标志,则仅在这是无存储响应或SSL无缓存响应时才重新验证。
  5. If the response status code is not cacheable or the response is no-cache or no-store or if the expiration time is before the Date of the response, revalidate. 如果响应状态代码不可缓存,或者响应为无缓存或无存储,或者到期时间在响应日期之前,请重新验证。
  6. If there is a query paramater and the response does not have an explicit Expires or max-age, revalidate. 如果存在查询参数,并且响应没有明确的Expires或max-age,请重新验证。
  7. If the response expiration time is in the past, revalidate (unless the "only revalidate once per session user preference is set"). 如果响应过期时间是过去的时间,请重新验证(除非“仅设置每个会话用户首选项一次重新验证”)。

So for your case, there should not be a conditional GET, assuming you actually set expires or max-age information on your 200 response. 因此,对于您的情况,假设您在200个响应中实际设置了过期或最大年龄信息,则不应有条件地获取GET。

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. 也就是说,某些试图为Firefox跟踪HTTP信息的工具实际上会影响重新验证行为,因此您可能会遇到这种情况。

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). 我建议您按照https://developer.mozilla.org/en/HTTP_Logging中的步骤创建日志,如果您可以找到日志的正确部分,它会顺便告诉您执行条件GET的确切原因(搜索“ nsHttpChannel :: CheckCache enter”,用于实现上述逻辑的函数的日志记录)。

As explained in Boris' answer, one of conditions that trigger conditional request is presence of Vary header. 如Boris的回答所述,触发条件请求的条件之一是Vary标头的存在。 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. 通常,您不希望删除Accept-Encoding上的变量,但是在进行URL版本控制时,可以做的事情和最好的事情就是不要让浏览器重新验证。 In your case it's Etag header. 在您的情况下,它是Etag标头。 It can as well be Last-Modified header. 它也可以是Last-Modified头。 Example code for varnish to do that for you may look like this: 清漆为您完成此操作的示例代码如下所示:

  sub vcl_recv {
  [..]
        if (req.url ~ "\?v=\w+$") {
          set req.http.X-Versioned = "1";
        }
  [..]
  }

  sub vcl_deliver {
  [..]
        if (req.http.X-Versioned) {
          unset resp.http.Etag;
        }
  [..]
  }

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. Firefox确实执行HTTP请求以获取文件信息,而不是文件本身。 This actually means firefox is doing this smarter then IE is doing. 实际上,这意味着firefox比IE更加智能。

The request firefox does is just a couple of bytes large (filesize, date etc). firefox所做的请求只有几个字节大(文件大小,日期等)。 so no matter what the name, firefox caches it (unless disabled). 因此,无论名称是什么,firefox都会对其进行缓存(除非已禁用)。 If the file itself changes, firefox decides to re-download the file. 如果文件本身发生更改,firefox决定重新下载该文件。

The thing you are pointing out is actually correct behavior. 您所指出的实际上是正确的行为。

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 or shipments_(unix_timestamp).js . 所以,你必须像shipments_v2.jsshipments_(unix_timestamp).js This will take care of proxies and any other kind of caching mechanisms. 这将处理代理和任何其他类型的缓存机制。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM