3

我正在尝试使用 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。

4

2 回答 2

5

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

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 是否在其控制器中设置了这个,但即使没有,它也会很快被缓存。
  • HerokuENV['TMPDIR']现在也设置了,因此您可以根据需要使用它来代替Rails.root + '/tmp'
于 2011-02-13T06:19:22.907 回答
0

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

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

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

于 2011-03-04T10:45:19.343 回答