10

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

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

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

这是场景:

  • 该应用程序的网页是空白的。根据 Chrome 的“检查元素”工具,这是因为它正在尝试 fetch 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的 ,浏览器似乎也忽略了它并继续使用它的缓存副本!

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

  • 在 war 目录中验证是否已app.nocache.js被覆盖并具有新的时间戳。
  • 从 Chrome 重新加载页面并再次验证服务器是否向app.nocache.js.
  • 浏览器再次尝试加载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
4

6 回答 6

5

避免浏览器缓存的最佳方法是将过期时间设置为现在并添加 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" )
}
于 2012-10-26T07:02:50.470 回答
5

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

正如评论所指出的,我们使用的是 GWT 2.7 版。

于 2015-11-13T10:17:23.643 回答
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 文件时在客户端动态添加唯一参数值。鉴于上述解决方案,我假设现在对您来说应该没什么大不了的。

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

于 2014-01-15T16:34:16.693 回答
2
  • 浏览器上的 app.nocache.js 已从 Web 服务器重新加载(200 OK),因为服务器上的文件比浏览器缓存更新。我验证了服务器返回的新文件的文件大小和时间戳是正确的。(这是 Chrome 报告的有关服务器 HTTP 响应的信息)

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

所以可能 Chrome 仍然使用旧版本。它可能很久以前就决定永远不必再次重新加载资源。清除缓存应该可以解决这个问题。然后确保在重新加载页面之前设置正确的缓存标头,请参阅不同类型资源的理想 HTTP 缓存控制标头

于 2012-10-25T23:53:17.997 回答
0

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

您需要按照其他评论中的说明配置缓存时间。

于 2017-07-05T03:24:18.877 回答
-1

在通过 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
于 2014-07-04T00:13:59.693 回答