如果路径中有一个querystring, Firefox是否缓存javascript并在没有请求的情况下使用它?

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

本文关键字:请求 情况下 querystring 有一个 路径 Firefox javascript 缓存 是否 如果      更新时间:2023-09-26

我想做的是在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。Firefox缓存了这些文件,但是当我下次加载该页面时,Firebug显示了一个304响应,表明它仍然对该文件进行了网络请求,然后发现它没有更改。

所以我的问题是,当有一个查询字符串时,火狐会忽略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

对于缓存的响应,Firefox用来决定是否进行条件GET的逻辑如下:

  1. 如果有相关的Vary头,请重新验证
  2. 如果这个请求应该是从缓存中强制加载的,不要重新验证。
  3. 如果这个请求有"always validate"标志,重新验证。
  4. 如果这个请求有"never validate"标志,那么只有当这是一个无存储响应或SSL无缓存响应时才重新验证。
  5. 如果响应状态码不可缓存或响应为无缓存或无存储,或者如果过期时间在响应日期之前,请重新验证。
  6. 如果有查询参数,而响应没有明确的Expires或max-age,则重新验证。
  7. 如果响应过期时间在过去,则重新验证(除非设置了"每会话用户偏好只重新验证一次")

因此,对于您的情况,不应该有一个条件GET,假设您实际设置过期或最大年龄信息的200响应。

也就是说,一些试图为Firefox跟踪HTTP信息的工具实际上会影响重新验证行为,所以您可能会遇到这种情况。

我建议按照https://developer.mozilla.org/en/HTTP_Logging中的步骤创建一个日志,它会顺便告诉你为什么要做条件GET,如果你能找到日志的正确部分(搜索"nsHttpChannel::CheckCache enter"从实现上述逻辑的函数中获取日志)。

你看到的是与实际下载文件不同的东西,然后说它没有改变。

Firefox确实执行HTTP请求来获取文件信息,而不是文件本身。这实际上意味着firefox比IE做得更聪明。

firefox的请求只是几个字节大(文件大小,日期等)。所以不管名字是什么,firefox都会缓存它(除非被禁用)。如果文件本身发生变化,firefox决定重新下载该文件。

你所指出的其实是正确的行为。

如果您想绝对确保文件将被重新加载,最好将版本号/缓存破坏字符串直接放在文件名中。所以会有shipments_v2.jsshipments_(unix_timestamp).js。这将照顾代理和任何其他类型的缓存机制。

正如Boris的回答所解释的那样,触发条件请求的条件之一是Vary报头的存在。您通常不希望删除Accept-Encoding上的变量,但是当您有URL版本控制时,您可以做的和最好做的事情是让浏览器没有任何东西可以重新验证。在您的例子中,它是Etag header。它也可以是Last-Modified header。varnish的示例代码可能如下所示:

  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;
        }
  [..]
  }