通过更改 ActionController::Base#page_cache_directory 在 Heroku 上使用 Jammit 进行静态资源缓存

StackOverflow https://stackoverflow.com/questions/4977780

  •  12-11-2019
  •  | 
  •  

我正在尝试使用 Jammit 为部署在 Heroku 上的 Rails 应用程序打包 CSS 和 JS,但由于 Heroku 的只读文件系统,该应用程序无法开箱即用。我见过的关于如何执行此操作的每个示例都建议提前构建所有打包的资产文件。由于 Heroku 基于 Git 的部署,这意味着每次这些文件发生更改时,您都需要单独提交到存储库,这对我来说不是一个可接受的解决方案。相反,我想更改 Jammit 用于将缓存包写入的路径 #{Rails.root}/tmp/assets (通过改变 ActionController::Base#page_cache_directory),它在 Heroku 上是可写的。

我不明白的是如何使用缓存的文件而不每次都访问 Rails 堆栈,甚至使用缓存包的默认路径。让我解释一下我的意思:

当您使用 Jammit 的助手包含一个包时,它看起来像这样:

<%= include_javascripts :application %>

它生成这个脚本标签:

<script src="/assets/application.js" type="text/javascript"></script>

当浏览器请求此 URL 时,实际发生的情况是它被路由到 Jammit::Controller#package, ,它将包的内容呈现给浏览器,然后将缓存的副本写入 #{page_cache_directory}/assets/application.js. 。这个想法是,这个缓存文件是基于第一个请求构建的,后续请求应该直接提供缓存文件,而不需要访问 Rails 堆栈。我查看了 Jammit 代码,但不明白这是如何发生的。是什么阻止了后续请求 /assets/application.js 从简单的路由到 Jammit::Controller 再次并且不再使用缓存的文件?

我的猜测是,我没有看到某个地方有一个 Rack 中间件,如果文件存在,它会提供服务;如果文件不存在,则将请求转发到控制器。如果是这样的话,该代码在哪里?以及改变时它会如何工作 ActionController::Base#page_cache_directory (有效地更改 Jammit 写入缓存包的位置)?自从 #{Rails.root}/tmp 位于公共文档根目录之上,没有映射到该路径的 URL。

有帮助吗?

解决方案

好问题!我自己没有设置这个,但这是我一直想研究的东西,所以你促使我这样做。这是我会尝试的(我很快就会自己尝试一下,但你可能会比我先一步)。

config.action_controller.page_cache_directory = "#{Rails.root}/tmp/page_cache"

现在将您的 config.ru 更改为:

require ::File.expand_path('../config/environment',  __FILE__)
run Rack::URLMap.new(
   "/"       => Your::App.new,
   "/assets" => Rack::Directory.new("tmp/page_cache/assets"))

只要确保里面没有任何东西 public/assets, ,因为它永远不会被拾取。

笔记:

  • 这是针对 Rails 3 的。不确定 Rails 2 下的解决方案。
  • 看起来像 Rack::Directory 将缓存控制标头设置为 12 小时,以便 Heroku 会将您的资源缓存到 Varnish。不确定 Jammit 是否在其控制器中设置了此设置,但即使没有设置,它也会很快被缓存。
  • Heroku 还设置 ENV['TMPDIR'] 现在也一样,所以你可以用它来代替 Rails.root + '/tmp' 如果你希望。

其他提示

这可能有用,它适用于不同的 gem,但想法相似,我正在尝试让它与普通的资产助手一起使用。

http://devcenter.heroku.com/articles/using-compass

不幸的是,如果不修补/重写资产助手模块(类似于耦合的意大利面条),似乎很难让 Rails 做到这一点。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top