【问题标题】:How to make browser stop caching GWT nocache.js如何让浏览器停止缓存 GWT nocache.js
【发布时间】:2012-10-25 18:31:12
【问题描述】:

我正在使用 GWT 开发一个 Web 应用程序,并且在浏览器中缓存 app.nocache.js 文件时发现了一个疯狂的问题,即使 Web 服务器发送了该文件的新副本!

我正在使用 Eclipse 编译应用程序,该应用程序在开发模式下工作。为了测试生产模式,我有一个虚拟机 (Oracle VirtualBox),在我的主机 (Windows 7) 上运行 Ubuntu 来宾操作系统。我在虚拟机中运行 lighttpd 网络服务器。虚拟机正在共享我项目的 war 目录,而 Web 服务器正在为该目录提供服务。

我使用 Chrome 作为浏览器,但同样的事情发生在 Firefox 中。

这是场景:

  • 应用程序的网页是空白的。根据 Chrome 的“检查元素”工具,这是因为它正在尝试获取不存在的 6E89D5C912DD8F3F806083C8AA626B83.cache.html (404 not found)。
  • 我检查了war目录,果然,那个文件不存在。
  • 浏览器上的app.nocache.js 已从 Web 服务器重新加载 (200 OK),因为服务器上的文件比浏览器缓存更新。我验证了服务器返回的新文件的文件大小和时间戳是正确的。 (这是 Chrome 报告的有关服务器 HTTP 响应的信息)
  • 但是,如果我在浏览器上打开app.nocache.js,javascript指的是6E89D5C912DD8F3F806083C8AA626B83.cache.html!!!也就是说,即使网络服务器发送了一个新的app.nocache.js,浏览器似乎也忽略了它并继续使用它的缓存副本!

  • 转到 Google->在 Eclipse 中编译 GWT。重新编译整个东西。

  • 在 war 目录中验证 app.nocache.js 是否已被覆盖并具有新的时间戳。
  • 从 Chrome 重新加载页面并再次验证服务器是否向 app.nocache.js 发送了 200 OK 响应。
  • 浏览器再次尝试加载6E89D5C912DD8F3F806083C8AA626B83.cache.html 并失败。浏览器仍在使用 app.nocache.js 的旧缓存副本。
  • 绝对确定在 war 目录中没有任何内容指向 6E89D5C912DD8F3F806083C8AA626B83.cache.html(通过 find 和 grep)

出了什么问题?为什么浏览器缓存这个nocache.js文件,即使服务器正在发送一个新副本?


这是在浏览器中单击重新加载时 HTTP 请求/响应标头的副本。在此跟踪中,服务器内容自上次 GET 以来尚未重新编译(但请注意,nocache.js 的缓存版本仍然错误!):

Request URL:http://192.168.2.4/xbts_ui/xbts_ui.nocache.js
Request Method:GET
Status Code:304 Not Modified
Request Headersview source
Accept:*/*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Host:192.168.2.4
If-Modified-Since:Thu, 25 Oct 2012 17:55:26 GMT
If-None-Match:"2881105249"
Referer:http://192.168.2.4/XBTS_ui.html
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4
Response Headersview source
Accept-Ranges:bytes
Content-Type:text/javascript
Date:Thu, 25 Oct 2012 20:27:55 GMT
ETag:"2881105249"
Last-Modified:Thu, 25 Oct 2012 17:55:26 GMT
Server:lighttpd/1.4.31

【问题讨论】:

  • 顺便说一句,这似乎类似于stackoverflow.com/questions/3407649/…,但它不包含任何帮助我解决此问题的信息。
  • 是的,似乎正在发生正确的事情,因为该页面显示“If-Modified-Since fetch 就足够了”。我可以从 Chrome Inspect Element 工具中得知浏览器在 GET 请求中发送了“If-Modified-Since:Thu, 25 Oct 2012 17:03:53 GMT”,而服务器以“Last-Modified:Thu, 25 2012 年 10 月 17:55:26 GMT"
  • 添加了 HTTP 请求/响应标头跟踪,以便潜在帮助者更清楚地了解这一点。
  • 我怀疑问题在于浏览器正在猜测 nocache.js 文件的新鲜度生命周期,并确定该文件仍然是“新鲜的”。这是来自阅读 HTTP RFC 第 13.2.4 节:“如果没有任何过期,Cache-Control: max-age 或 Cache-Control: s-maxage(参见第 14.9.3 节)出现在响应中,并且响应确实不包括缓存的其他限制,缓存可以使用启发式计算新鲜生命周期。” (来自w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13

标签: gwt browser-cache lighttpd


【解决方案1】:

避免浏览器缓存的最佳方法是将过期时间设置为现在并添加 max-age=0 和 must-revalidate 控件。

这是我在 apache-httpd 中使用的配置

ExpiresActive on
<LocationMatch "nocache">
   ExpiresDefault "now"
   Header set Cache-Control "public, max-age=0, must-revalidate"
</LocationMatch>
<LocationMatch "\.cache\.">
   ExpiresDefault "now plus 1 year"
</LocationMatch>

您对 lighthttpd 的配置应该是

server.modules = (
    "mod_expire",
    "mod_setenv",
)
...
$HTTP["url"] =~ "\.nocache\." {
  setenv.add-response-header = ( "Cache-Control" => "public, max-age=0, must-revalidate" )
  expire.url = ( "" => "access plus 0 days" )
}

$HTTP["url"] =~ "\.cache\." {
  expire.url = ( "" => "access plus 1 years" )
}

【讨论】:

  • 谢谢。我修复了 lighttpd 配置中的一些拼写错误。感谢您将 Apache 配置转换为 lighttpd。
【解决方案2】:

我们遇到了类似的问题。我们发现 nocache.js 的时间戳没有用 gwt compile 更新,所以必须在构建时触摸文件。然后我们还应用了来自@Manolo Carrasco Moñino 的修复程序。我写了一篇关于这个问题的博客。 http://programtalk.com/java/gwt-nocachejs-cached-by-browser/

评论也指出,我们使用的是 GWT 2.7 版。

【讨论】:

  • 时间戳不变是我们的问题。我相信这只是 GWT 2.7 中的一个错误。感谢您的博文!
  • 很好的答案。现在我第一次了解到 Shift+F5 是一个临时解决方案。
【解决方案3】:

有两个简单的解决方案(第二个是第一个的修改版本)

1) 将引用 *.nocache.js 的 *.html 文件重命名为,即 MyProject.html 到 MyProject.jsp 现在在 MyProject.html 中搜索 *.nocache.js 脚本的位置

<script language="javascript" src="MyProject/MyProject.nocache.js"></script>

为JS文件添加一个动态变量作为参数,这将确保每次都从服务器返回实际内容。以下是示例

<script language="javascript" src="MyProject/MyProject.nocache.jsp?dummyParam=<%= "" + new java.util.Date().getTime() %>"></script>

说明:dummyParam 没有用,但会得到我们想要的结果,即返回 200 代码而不是 304

注意:如果您将使用此技术,则需要确保您指向正确的 jsp 文件以加载您的应用程序(在此更改之前,您使用 HTML 文件加载您的应用程序)。

2) 如果您不想使用 JSP 解决方案并想坚持使用您的 html 文件,那么您将需要 java 脚本在加载 nocache 文件时在客户端动态添加唯一参数值。鉴于上述解决方案,我假设现在对您来说应该没什么大不了的。

我已经成功使用了第一种技术,希望这会有所帮助。

【讨论】:

    【解决方案4】:
    • 浏览器上的 app.nocache.js 已从 Web 服务器重新加载 (200 OK),因为服务器上的文件比浏览器缓存更新。我验证了服务器返回的新文件的文件大小和时间戳是正确的。 (这是 Chrome 报告的有关服务器 HTTP 响应的信息)

    我不会依赖这个。我在 Chrome 的开发工具中看到了一些奇怪的行为,其中网络选项卡与缓存相结合(至少,它对我来说不是 100% 透明的)。如有疑问,我通常还是会咨询 Firebug。

    所以可能 Chrome 仍然使用旧版本。它可能很久以前就决定永远不必再次重新加载资源。清除缓存应该可以解决这个问题。然后确保在重新加载页面之前设置正确的缓存头,参见例如Ideal HTTP cache control headers for different types of resources.

    【讨论】:

      【解决方案5】:

      以认知模式打开页面只是为了摆脱缓存问题并解锁自己。

      你需要像其他cmets中提到的那样配置缓存时间。

      【讨论】:

        【解决方案6】:

        在通过 Apache 阻止缓存失败后,我创建了一个 bash 脚本,root 在我的 Linux Tomcat 服务器上的 cron 作业中每分钟运行一次。

        #!/bin/bash
        #
        # Touches GWT nocache.js files in the Tomcat web app directory to prevent caching.
        # Execute this script every minute in a root cron job.
        #
        cd /var/lib/tomcat7/webapps
        find . -name '*nocache.js' | while read file; do
            logger "Touching file '$file'"
            touch "$file"
        done
        

        【讨论】:

        • 使用根脚本来访问由您的网络服务器提供的文件确实是个坏主意——尤其是。因为您应该做的是确保使用正确的 HTTP 标头来提供内容(如果浏览器 - 或中间代理 - 善意地缓存了内容,您的服务器甚至不会被询问)。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-03-25
        • 1970-01-01
        • 2022-01-21
        • 2016-02-11
        • 2021-07-29
        • 1970-01-01
        • 2023-03-21
        相关资源
        最近更新 更多