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

发布于 2024-12-07 13:42:27 字数 1466 浏览 2 评论 0原文

我想要做的是在 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

ゞ记忆︶ㄣ 2024-12-14 13:42:27

Firefox 用于决定是否在给定缓存响应的情况下进行条件 GET 的逻辑如下所示:

  1. 如果存在相关的 Vary 标头,则重新验证。
  2. 如果该请求应该从缓存中强制加载,则不要重新验证。
  3. 如果此请求具有“始终验证”标志,则重新验证。
  4. 如果此请求具有“从不验证”标志,则仅当这是无存储响应或 SSL 无缓存响应时才重新验证。
  5. 如果响应状态代码不可缓存或响应为无缓存或
    no-store 或者如果过期时间早于响应日期,则重新验证。
  6. 如果存在查询参数并且响应没有明确的 Expires 或 max-age,则重新验证。
  7. 如果响应过期时间已过去,请重新验证(除非设置了“每个会话用户首选项仅重新验证一次”)。

因此,对于您的情况,假设您实际上在 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:

  1. If there is a relevant Vary header, revalidate.
  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.
  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.
  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.

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).

初相遇 2024-12-14 13:42:27

您看到的内容与实际下载的文件不同,然后说它没有改变。

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.

最笨的告白 2024-12-14 13:42:27

如果您想绝对确定您的文件将被重新加载,最好将版本号/缓存破坏程序字符串直接放在文件名中。因此,您将拥有类似 shipments_v2.jsshipments_(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 or shipments_(unix_timestamp).js. This will take care of proxies and any other kind of caching mechanisms.

时光无声 2024-12-14 13:42:27

正如鲍里斯的回答所解释的,触发条件请求的条件之一是存在 Vary 标头。您通常不想删除 Accept-Encoding 上的变化,但是当您有 URL 版本控制时,您可以做的以及最好做的事情是让浏览器没有任何可重新验证的内容。在你的例子中它是 Etag 标头。它也可以是 Last-Modified 标头。
清漆为您执行此操作的示例代码可能如下所示:

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

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:

  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;
        }
  [..]
  }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文