为什么 Chrome DevTools 说我的静态资源显式 non-cacheable 而映射到 Spring 的 mvc:resources?

Why does Chrome DevTools say my static resource is explicitly non-cacheable while mapped with Spring's mvc:resources?

我正在使用Spring MVC 4,并按如下方式处理静态资源(缓存一年):

<mvc:resources mapping="/static/**" location="/static/" cache-period="31556926" />

我的 static 文件夹中有一个 app.js 文件。启动 audit with the Chrome DevTools 时,app.js 文件出现在以下部分:

The following resources are explicitly non-cacheable. Consider making them cacheable if possible: app.js

此静态文件请求的响应 headers 是:

Date: Mon, 23 Feb 2015 18:02:49 GMT
Expires: Tue, 23 Feb 2016 23:51:36 GMT
Cache-Control: max-age=31556926, must-revalidate

我的静态资源是否被浏览器缓存得很好?为什么 Chrome DevTools 告诉我 app.js 明确是 non-cacheable?

我在 chrome 审计中看到了类似的奇怪现象,似乎一致认为 Chrome 审计可能有问题:

Google Chrome audit on caching

除了那个引用问题中的其他答案之外,我还有两个我尚未彻底测试但我认为可能导致问题的理论:

1) 饼干

当您将 cookie 与图像一起传递时,这在 Java 应用程序中经常发生(jsession 和可能在过滤器中设置的各种其他 cookie)。问题是您似乎没有在 header 中向我们展示任何 cookie。此外,较新版本的 chrome 审计通常将此作为一个单独的错误进行抱怨。

2) 通过 DOM 更改动态请求内容

一些 Java 脚本库,特别是 ACE 编辑会动态添加字体和/或 Java 脚本(又名 AMD),偶尔会向 URL 添加查询参数。这似乎混淆了 chrome 审计。因此,也许您的 app.js 正在通过其他一些 Java 脚本动态添加(即添加 <script...src= ></script> 元素) and/or 将查询参数添加到 URL?

更新

我想我知道你的具体问题是什么。 Chrome 审核不喜欢 must-revalidate 不幸的是,当您指定 cache-period 大于 0 时,Spring ResourceHttpRequestHandler 将始终添加 must-revalidate 到缓存控件 header。如果您不设置 cache-period(它将是 -1),那么 Spring 仍将执行缓存 headers 但不会执行 must-revalidate(但是没有 max-age 导致另一个审核错误消息 以下资源缺少缓存过期时间。浏览器可能不会缓存未指定过期时间的资源:).

不幸的是,您将需要编写一个过滤器来删除 must-revalidate 或创建您自己的 ResourceHttpRequestHandler probably extending and overriding cacheForSeconds.

版本

其他一些选项是使用资产管道库,如 Wro4J 或将 app.js 上传到您的 CDN。