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

Jim*_*dra 3 ruby-on-rails heroku jammit

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

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

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

<%= include_javascripts :application %>
Run Code Online (Sandbox Code Playgroud)

生成此脚本标记:

<script src="/assets/application.js" type="text/javascript"></script>
Run Code Online (Sandbox Code Playgroud)

当浏览器请求此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.

wup*_*tah 5

好问题!我自己没有把它设置好,但这是我一直想要研究的东西,所以你促使我这样做.这是我会尝试的(我会很快给自己一个镜头,但你可能会打败我).

config.action_controller.page_cache_directory = "#{Rails.root}/tmp/page_cache"
Run Code Online (Sandbox Code Playgroud)

现在将config.ru更改为:

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

只要确保没有任何东西public/assets,因为这不会被拿起.

笔记:

  • 这适用于Rails 3.不确定Rails 2下的解决方案.
  • 看起来Rack::Directory将缓存控制标头设置为12小时,因此Heroku会将您的资产缓存到Varnish.不确定Jammit是否在其控制器中设置了它,但即使它没有,它也会很快缓存.
  • Heroku ENV['TMPDIR']现在也设置了,所以你可以使用它而不是Rails.root + '/tmp'你想要的.