为什么在文件名中包含散列更好地用于缓存而不是将时间戳作为查询参数附加?

Kri*_*ian 5 revision caching browser-cache node.js gruntjs

在使用Grunt构建时,我遇到了修复/缓存静态资产的rev任务和cachebreaker任务.

一个使用文件名覆盖,另一个使用时间戳作为查询参数.显然,一个比另一个更优选.

为什么一个比另一个好?

Zla*_*tko 8

您提供的链接中的一条评论说得最好:

"一旦你有了独特的名字,你也可以使用非常积极的缓存标题,这对性能很有帮助."

使用时间戳,您可以在他们的示例中使用此版本:

<script type="text/javascript" src="@routes.Assets.at("javascripts/main.js")?nocache=@(new Date().getTime())"></script>
Run Code Online (Sandbox Code Playgroud)

每次请求脚本时,它都会添加一个唯一的时间戳.这意味着浏览器永远不会缓存它.

替代方案,但类似的方法是添加内部计数器.像这样的东西:

<script type="text/javascript" src="@routes.Assets.at("javascripts/main.js")?version=1234"></script>
Run Code Online (Sandbox Code Playgroud)

这个更好一点 - 因为每次更改资产中的某些内容时,都会更改版本号.然后,浏览器只加载一次版本,并将其保存在缓存中,直到您构建新版本的静态资产.

缺点是你必须以某种方式跟踪版本号.你可以使用静态的东西,比如git commit的一部分,但仍然可以监视这个版本+然后你依赖于git(或svn或你使用的任何东西).

哈希版本,例如javascripts/main.ab4c6c83e4fa9c.js具有以下好处:

  • 它只与一个文件相关 - 所以它只依赖于main.js. 无论你在其他任务中使用什么,我们都关心main.js. 你不关心日期或版本或任何东西.
  • 它只与文件内容有关.因此,如果您更改了js代码,您将生成不同的内容(例如,来自minifiers),因此哈希将是不同的.浏览器将被强制加载新版本.
  • 如果您再次将内容更改为与以前相同(不仅仅是恢复到该版本,而是在未来的版本中也会出现同一点),该内容的哈希值将与浏览器已有的哈希值相同在缓存中.

所以有了这些,你不关心日期,文件,任何东西,你只需要创建你的Javascript.您还可以告诉浏览器将其缓存为一年,或者永久.而且您确定如果您在版本之间切换,则用户会获得正确的版本.