我有一个简单的 Maven webapp,它使用单个 JSP 和 RequireJS 来提供单页 Javascript-heavy 应用程序。我一直在寻找可以在构建过程中用来对资产进行指纹识别的东西(.js、.css 等),但没有找到任何可以解决这个问题的东西。
我希望在内容更改时更改资产文件名,以便我可以告诉浏览器将它们缓存很长时间,但仍会在它们更改时下载最新的。我还需要对这些资产的任何引用,以便在它们更改时进行更新。无论我使用什么,都必须与 RequireJS 一起使用。
有什么建议么?
我有一个简单的 Maven webapp,它使用单个 JSP 和 RequireJS 来提供单页 Javascript-heavy 应用程序。我一直在寻找可以在构建过程中用来对资产进行指纹识别的东西(.js、.css 等),但没有找到任何可以解决这个问题的东西。
我希望在内容更改时更改资产文件名,以便我可以告诉浏览器将它们缓存很长时间,但仍会在它们更改时下载最新的。我还需要对这些资产的任何引用,以便在它们更改时进行更新。无论我使用什么,都必须与 RequireJS 一起使用。
有什么建议么?
我最近通过使用 RequireJS 的urlArgs配置选项解决了这个问题。我怀疑实际上重命名文件以包含时间戳是否可行,这会使构建和 RequireJS 配置复杂化很多,并且很可能需要 hack 来进行开发或生产。所以,按逻辑顺序:
在 pom.xml 中:
<properties>
(...)
<build.version>${maven.build.timestamp}</build.version>
</properties>
在主 JSP 文件中:
<script type="text/javascript">
var require = {
(...)
urlArgs: 'v=${build.version}',
};
</script>
<link rel="stylesheet" type="text/css" href="style.css?v=${build.version}"></link>
<script data-main="app" src="libs/require.js?v=${build.version}"></script>
在 require.js 导入之前定义require对象以使 urlArgs 工作很重要
pom.xml,再次:
<resources>
(...)
<resource>
<targetPath>${project.build.directory}/filteredWebapp</targetPath>
<directory>src/main/webapp</directory>
<filtering>true</filtering>
</resource>
</resources>
r.js 的 buildconfig(顺便说一句。我正在使用 requirejs-maven-plugin来桥接 Maven 和 r.js):
({
appDir: '${project.build.directory}/filteredWebapp',
dir: '${project.build.directory}/${project.build.finalName}',
(...)
})
我必须将过滤 src/main/webapp 的结果存储在一个新文件夹(即filteredWebapp)中,以确保 r.js 的输入已经包含构建时间戳而不是占位符。我最初的 r.js buildconfig 版本是直接从 src/main/webapp 读取源文件;工作正常,但绕过了 maven 过滤(即 r.js 编译的输出仍然包含${build.timestamp}占位符)
注意:配置开发版本以使用这种机制可能很棘手(如果可能的话,我还没有尝试过)。不过,对我来说,“v=${build.timestamp}”参数的存在和缓存破坏的缺乏在实践中并不是问题。
在此过程中还有许多其他障碍和陷阱,但我假设您设法解决了这些问题,因为您只是专门要求指纹识别。希望有帮助!
实际上,我强烈反对将查询参数用作“缓存杀手”,因为这可能会导致所谓的缓存中毒。例如:假设您有一个 cdn 或一个前端缓存服务器和多个应用程序服务器。您上传文件的新版本并更改查询参数。但是新文件仍然没有。交付给所有应用服务器。缓存服务器然后转到仍然包含旧版本的服务器之一(因为它看到查询参数已更改),获取并缓存它。所以现在缓存服务器有一个旧文件,一个新的缓存杀手认为它是最新的,不再尝试从服务器获取它。