33

我在Rails中开始一个新项目,它看起来像application.js清单文件正在做一些有趣的事情,我引用了javascripts - 是否缓存这些文件作为资产管道?清除Rails资产管道中的缓存

这是发生了什么事。我添加了一个名为jquery.autoresize.js给供应商/资产/ JavaScript的文件夹中的JavaScript文件,然后引用清单中像这样的application.js文件:

//= require jquery.autoresize.js 

然后,我开始了在轨服务器。但是在浏览我的应用程序后,我意识到我不小心添加了错误版本的jquery.autoresize.js文件。所以,我删除了该文件,然后将正确的版本添加到vendor/assets/javascripts文件夹。但是,令我惊恐的是,当我重新加载页面时,它仍在加载旧的JavaScript文件。

我试图清空我的浏览器缓存,然后退出并重新启动Rails服务器,但无济于事。我通过简单地重命名我的JavaScript文件并引用新名称,这很好地解决了一个解决方案。但是这必须有更好的解决方案。

新资产管道缓存了您引用的文件吗?如果是这样,我该如何清除缓存?谢谢你的帮助!

回答

48

我假设我们正在谈论生产环境。

当您更改生产环境中的任何JavaScript或样式表时,您需要运行rake assets:precompile;此任务编译和压缩各种.js和.css文件,并创建由视图加载的application.js和application.css文件。

这是可能的,如果你用一个旧的时间戳版本替换jquery.autoresize.js,预编译步骤可以跳过它,想着编译的版本是最新的更新。您可以通过先运行rake assets:clean来避免这种情况,迫使它从零开始重建public/assets目录中的所有内容。

+0

啊,非常有趣,谢谢你的想法。我实际上是在我的本地开发环境中执行此操作,并且我从不运行rake资源:预编译。那么,也许这使得它的行为有所不同?你认为开发环境会使它的行为与我原先描述的一样吗? – 2012-09-06 04:03:47

+2

在开发环境中,不使用哈希文件名,因此所有内容都基于文件修改日期。 (在浏览器中查看源代码以查看HTML标头中的脚本链接。)我的猜测是,在开发环境中,替换文件具有较早的修改日期,因此浏览器仅使用其缓存版本。你的编辑更新了文件的mod时间,这就是浏览器最终获取新版本的原因。 – benzado 2012-09-06 18:10:10

+0

太棒了。感谢您帮助我弄清楚这一点。我会修改问题的内容,以更好地解释问题并为您提供帮助。 – 2012-09-06 19:02:35

23

每次编辑内容时,Rails都会自动清除单个文件的缓存。 要清除单个文件的缓存,只需打开文件,编辑一行代码并重新保存即可。 Rails将清除该文件的缓存,并且浏览器将在下次加载页面时加载新文件。

jquery.autoresize.js使用旧缓存版本的文件的原因是,旧版本被删除,然后新版本被复制并粘贴到相同的文件夹中。由于文件本身从未编辑,Rails继续使用缓存的旧文件。

这是因为资产管道使用指纹识别缓存。

指纹识别是一种使文件内容依赖于文件名称 的技术。当文件内容改变时, 文件名也被改变。对于静态或不频繁的内容 进行更改,这提供了一种简单的方法来判断文件的两个版本是否相同,即使是在不同的服务器或部署日期也是如此。

当一个文件名是独一无二的,根据其内容,HTTP头可以 被设置为鼓励缓存无处不在(无论是在CDN中,在互联网服务供应商,在 网络设备,或在网络浏览器),以保持自己的 副本内容。当内容更新时,指纹会改变。 这将导致远程客户端请求 内容的新副本。这通常称为缓存清除。

Rails用于指纹识别的技术是将内容的散列 插入到名称中,通常在末尾。例如一个CSS 文件全局。CSS可以用其内容的MD5摘要改名:

global-908e25f4bf641868d8683022a5b62f54.css 

所以,如果你删除你的清单引用文件,然后在一个新的文件复制具有相同的名称,高速缓存破坏从未发生。当您编辑文件时,指纹会启动,并为文件名称生成一个新的散列。这为该文件破坏了缓存

有关完整的故事,请参阅What is Fingerprinting and Why Should I Care?

+1

我不认为这是正确的。指纹基于文件的内容。如果删除一个文件并将其替换为具有相同名称的* * *,则会得到不同的指纹和不同的文件名。 – benzado 2012-09-05 01:18:28

+1

感谢您的支持。您最近在自己的项目中尝试了这个吗?因为我可以肯定地确认,当我创建这个问题时,我可以通过浏览器加载新文件的唯一方法是编辑一行代码并重新保存它。如果它只是通过删除文件并将其替换为具有相同名称的新文件而为您工作,我很乐意听到它。 – 2012-09-05 22:26:11

+0

我有一个不同的资产管道问题,这是我遇到这个问题。你说:“如果你删除了一个你在清单中引用的文件,然后复制一个新文件具有相同的名称,缓存破坏永远不会发生。如果新/旧文件具有*相同的内容*,那么*只会*为真,在这种情况下,谁在乎你拥有哪个版本?如果您正在讨论生产模式,您需要运行'rake assets:precompile'将这些文件放入'public/assets'目录;这应该是解决方案,除非你已经改变了默认配置。 – benzado 2012-09-05 23:15:56

6

我在我的application.rb中使用config.assets.version = '1.01019'来破坏整个缓存。当我想要推出一个完整的新版本时,我增加了版本,这个技巧。这考虑到了Rails因任何原因不会重新编译为资产的边缘情况。

25

也试试rake assets:clobber。这将完全重置所有内容并删除所有已编译的资产。此外,我经常需要在推进生产前设置环境:RAILS_ENV=production rake assets:precompile

+0

+1!这个解决方案为我工作。我正在开发一个自定义资产管道处理器,这使得Sprockets再次进入处理器。 Thx – MegaTux 2017-01-09 15:19:41

6

rake tmp:clear为我做了诡计,我使用less-rails。

+1

我必须这样做才能让browserify-rails进行更新,否则它将查找并使用已被删除的旧文件。 '轨道资产:干净'不适合这个。 – Ryan 2016-12-03 20:05:38

+0

该命令也会删除tmp目录中的pid文件。 – caiguanhao 2017-04-11 01:35:44