从 Rails 资产管道中清除缓存
Posted
技术标签:
【中文标题】从 Rails 资产管道中清除缓存【英文标题】:Clear the cache from the Rails asset pipeline 【发布时间】:2012-04-17 18:17:49 【问题描述】:我正在 Rails 中开始一个新项目,看起来 application.js 清单文件对我引用的 javascript 做了一些有趣的事情 - 它是否将这些文件缓存为资产管道的一部分?
这就是发生的事情。我在 vendor/assets/javascripts 文件夹中添加了一个名为 jquery.autoresize.js 的 javascript 文件,然后在 application.js 清单中引用该文件,如下所示:
//= require jquery.autoresize.js
然后我启动了 rails 服务器。但是在我的应用程序中浏览之后,我意识到我不小心添加了错误版本的 jquery.autoresize.js 文件。因此,我删除了该文件,然后将正确的版本添加到 vendor/assets/javascripts 文件夹中。但是,令我恐惧的是,当我重新加载页面时,它仍在加载旧的 javascript 文件。
我尝试清空浏览器缓存,然后退出并重新启动 Rails 服务器,但无济于事。我通过简单地重命名我的javascript文件并引用新名称来共同破解一个解决方案,效果很好。但必须有一个更好的解决方案。
新的资产管道是否会以某种方式缓存您引用的文件?如果是这样,我该如何清除该缓存?感谢您的帮助!
【问题讨论】:
我不敢相信我在这上面浪费了一个多小时。最终为我解决的问题是重置 浏览器的缓存! Chrome > 清除浏览数据 > 缓存的图像和文件 【参考方案1】:我假设我们谈论的是生产环境。
当您在生产环境中更改任何 javascript 或样式表时,您需要运行 rake assets:precompile
;此任务编译和压缩各种 .js 和 .css 文件,并创建您的视图加载的 application.js 和 application.css 文件。
如果您将jquery.autoresize.js
替换为具有较旧时间戳 的版本,则预编译步骤可能会跳过它,认为编译后的版本是最新的。您可以通过首先运行rake assets:clean
来避免这种情况,强制它从头开始重建public/assets
目录中的所有内容。
【讨论】:
啊,很有趣,谢谢你的想法。我实际上是在我的本地开发环境中执行此操作的,而且我从未运行过 rake assets:precompile。那么,也许这使它的行为有所不同?你认为开发环境会导致它按照我最初描述的方式运行吗? 在开发环境中,不使用散列的文件名,所以一切都基于文件修改日期。 (在浏览器中查看源代码以查看 html 标头中的脚本链接。)我的猜测是,在开发环境中,替换文件的修改日期较旧,因此浏览器只是使用其缓存版本。您的编辑更新了文件的修改时间,这就是浏览器最终获取新版本的原因。 太棒了。感谢您帮助我解决这个问题。我将修改问题和内容的内容以更好地解释并感谢您的帮助。 RAILS_ENV=development bundle exec rake assets:clean、RAILS_ENV=development bundle exec rake assets:precompile 和 RAILS_ENV=development bundle exec rails server 最终为我做了。【参考方案2】:也可以试试rake assets:clobber
。这将完全重置所有内容并删除所有已编译的资产。另外,我经常需要在推送到生产之前设置环境:RAILS_ENV=production rake assets:precompile
。
【讨论】:
+1!这个解决方案对我有用。我正在开发一个自定义资产管道处理器,这使得 Sprockets 再次进入处理器。谢谢 可能是最好的答案【参考方案3】:每次编辑内容时,Rails 都会自动清除单个文件的缓存。 要清除单个文件的缓存,只需打开文件,编辑一行代码,然后重新保存即可。Rails 将清除该文件的缓存,然后浏览器将在下次加载页面时加载新文件。
jquery.autoresize.js 使用文件的旧缓存版本的原因是因为旧版本被删除,然后新版本被复制并以相同的名称粘贴到同一个文件夹中。由于文件本身从未被编辑过,Rails 继续使用缓存的旧文件。
这是因为资产管道对缓存使用指纹。
指纹是一种使文件名依赖的技术 关于文件的内容。当文件内容发生变化时, 文件名也改变了。对于静态或不频繁的内容 改变,这提供了一种简单的方法来判断一个版本的两个版本是否 文件是相同的,即使跨不同的服务器或部署日期。
当文件名是唯一的并且基于其内容时,HTTP 标头可以 设置为鼓励无处不在的缓存(无论是在 CDN、ISP 还是 网络设备,或在网络浏览器中)保留自己的副本 内容。当内容更新时,指纹会发生变化。 这将导致远程客户端请求一个新的副本 内容。这通常称为缓存清除。
Rails 用于指纹识别的技术是插入哈希 将内容的名称放入名称中,通常放在末尾。例如一个 CSS 文件 global.css 可以用其内容的 MD5 摘要重命名:
global-908e25f4bf641868d8683022a5b62f54.css
因此,如果您删除清单中引用的文件,然后复制到具有相同名称的新文件中,则不会发生缓存破坏。当您编辑文件时,指纹会启动,并为文件名生成一个新的哈希值。这会破坏该文件的缓存。
有关完整故事,请参阅What is Fingerprinting and Why Should I Care?。
【讨论】:
我不认为这是正确的。指纹基于文件的内容。如果您删除一个文件并将其替换为不同同名文件,您将获得不同的指纹和不同的文件名。 感谢您的参与。您最近在自己的项目中尝试过吗?因为我可以肯定地确认,当我创建这个问题时,我可以让浏览器加载新文件的唯一方法是编辑一行代码并重新保存它。如果只需删除文件并将其替换为具有相同名称的新文件即可为您工作,我很想听听。 Aaron 是对的,我遇到了同样的问题(在开发模式下)并尝试了所有方法 -rake assets:clean
,然后是 rake assets:precompile
,以及再次复制新文件并重新启动服务器。直到我打开新文件,在最后添加了一些虚拟词,然后删除它们并保存文件之前,没有任何效果。 Rails 变得太复杂了——你知道,当简单的事情需要复杂的步骤才能完成时,情况就是如此。
不幸的是,甚至@user906230 的解决方案都不起作用。 Rails 只是继续为旧文件提供服务,除了直接调试资产管道之外,我已经完成了所有工作。如果有人解决了这个问题,请写评论。
而不是编辑文件,您可以在文件上运行touch
以更新其时间戳。您可以通过运行ls -l
并检查修改日期来查看这是否是问题。【参考方案4】:
rake tmp:clear
帮了我大忙,我正在使用 less-rails。
【讨论】:
我也必须这样做才能让 browserify-rails 更新,否则它会找到并使用已被删除的旧文件。rails assets:clean
不适用于此。
这是我在依赖于更改环境变量时正确重建文件的唯一方法。在这种情况下,Clean 和 Clobber 似乎还不够。【参考方案5】:
我在application.rb
中使用config.assets.version = '1.01019'
来破坏整个缓存。当我想推送一个完整的新版本时,我会增加版本,这样就可以了。这会处理那些 Rails 出于某种原因没有重新编译为资产的边缘情况。
【讨论】:
以上是关于从 Rails 资产管道中清除缓存的主要内容,如果未能解决你的问题,请参考以下文章
如何清除 Rails 动作缓存? (Rails.cache.clear 不起作用)