部署到子 URI 时,Rails 3.1 中的预编译资产损坏 [英] Broken precompiled assets in Rails 3.1 when deploying to a sub-URI

查看:26
本文介绍了部署到子 URI 时,Rails 3.1 中的预编译资产损坏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在更新 Rails 3 应用程序以使用 Rails 3.1,作为其中的一部分,我正在使用新的资产管道.到目前为止,除了一个我无法解决的相当烦人的问题之外,我已经让一切正常.

I'm in the process of updating a Rails 3 app to use Rails 3.1 and as part of that, am making use of the new asset pipeline. So far, I've got everything working apart from one rather annoying problem I can't solve.

应用程序及其所有资产在开发中运行良好,但在生产中,它使用Passenger (http://the-host/sub-uri/) 部署到子URI.这样做的问题是资产是在部署期间预编译的,我的一个 CSS(嗯,它是一个 .css.scss 文件)文件正在使用 image-url 来自 sass-rails gem 的助手.由于在预编译过程中,路径被硬编码到预编译的 CSS 文件中,因此不考虑 sub-uri:

The application and all its assets works fine in development, but in production it is deployed to a sub-URI using Passenger (http://the-host/sub-uri/). The problem with this is that the assets are pre-compiled during deployment and one of my CSS (well, it's a .css.scss file) files is making use of the image-url helper from the sass-rails gem. Since during the pre-compilation process, the paths are hard-coded into the precompiled CSS file, the sub-uri is not taken account of:

在我的 .css.scss 文件中:

body { background-image: image-url("bg.png"); }

编译后的application-.css文件中的结果:

The result in the compiled application-<md5-hash-here>.css file:

body { background-image: url(/assets/bg.png); }

它应该怎样才能正常工作:

What it should be to make it work correctly:

body { background-image: url(/sub-uri/assets/bg.png); }

这个场景是不是要求太多了?如果是这样,我将不得不切换回旧的非资产流水线方式,只从 public 提供我的图像和 CSS.然而,这似乎是应该考虑和解决的事情......?我错过了解决方案吗?

Is this scenario just asking too much? If so, I'll have to switch back to the old non-asset-pipelined way and just serve my images and CSS from public. However it seems like something which should have been thought about and solved...? Am I missing the solution?

编辑 1: 我应该注意使用 erb 解决方案反而产生了与预期相同的结果.

Edit 1: I should note that using the erb solution instead yields the same result, as one would expect.

编辑 2:回应 Benoit Garret 的评论

不,问题与 config.assets.prefix 无关.我尝试将其设置(设置为 /sub-uri/assets 而不是 /assets 的默认值),但结果证明这是错误的做法 - 看起来像这样设置已经与 Rails 应用程序的根相关,而不是服务器.删除它(并因此返回默认值)已经解决了所有导致的奇怪问题(并且有很多,所有资产最终都在 /sub-uri/sub-uri/assets - 它是都很奇怪).唯一的问题是 image-url 帮助器和朋友在预编译时不会拾取子 URI.不用说,这是合乎逻辑的,因为当它被预编译时,它不可能知道它在Passenger下运行时会以这种方式配置.我的问题是如何通知它这一点,从而在预编译结果中得到正确的路径.如果确实可以做到.

No, the problem isn't related to the config.assets.prefix. I tried setting that (to /sub-uri/assets rather than the default of /assets) but it turned out that was the wrong thing to do - it seems like this setting is already in relation to the root of the Rails app, not the server. Removing that (and thus returning to the default) has fixed all the weird issues that caused (and there were many, all the assets ended up in /sub-uri/sub-uri/assets - it was all very strange). The only problem is that the image-url helper and friends do not pick up the sub-URI when they are pre-compiled. Needless to say, this is logical since when it is pre-compiled, it couldn't possibly know that when it's running under Passenger, it'll be configured in this way. My question is how to inform it of this and thus end up with the correct paths in the precompiled result. If indeed it can be done.

我目前的解决方法是像这样在 CSS 中引用图像:url(../images/bg.png) 并将其放在非流水线的 public/images位置.几乎不理想,因为它不能从指纹识别和管道提供的所有内容中受益.

My current workaround is to reference the iamge in the CSS like this: url(../images/bg.png) and place it in the non-pipelined public/images location. Hardly ideal since it doesn't benefit from the fingerprinting and everything which the pipeline provides.

推荐答案

最后我想出了几个变通方法/解决方案.

Finally I've worked out a couple of workarounds/solutions.

1) 来自 https://github.com/rails/sass-rails/issues/17 看起来这可以在 sass-rails 中修复.我已经按照上面链接中提议的补丁的方式自己修补了 helpers.rb.我只是在 deploy.rb 的资产预编译行中设置所需的环境变量.

1) From https://github.com/rails/sass-rails/issues/17 it looks like this could get fixed in sass-rails. I've monkey-patched helpers.rb myself along the lines of the proposed patch in the link above. I simply set the required environment variable in the asset precompile line in deploy.rb.

我在一个文件 config/initializers/gem_patches.rb 中完成我所有的猴子补丁.在此文件中,我将此方法修补为:

I do all my monkey patching in a single file config/initializers/gem_patches.rb. In this file I patched this method as:

module Sass
  module Rails
    module Helpers
      protected
      def public_path(asset, kind)
        path = options[:custom][:resolver].public_path(asset, kind.pluralize)
        path = ENV['PRODUCTION_URI'] + path if ENV['PRODUCTION_URI']
        path
      end
    end
  end
end

2) 或者,如果您可以在 CSS 中嵌入图像,将样式表更改为具有 .erb 扩展名,并将 image-url("bg.png") 替换为 url(<%= asset_data_uri "bg.png" %>) 无需更改 sass-rails 即可工作.asset-data-uri 不作为纯 Sass 函数存在,因此您必须使用 Rails 助手 asset_data_uri.

2) Alternatively if you are ok to embed images in the CSS, changing the stylesheet to have a .erb extension, and replacing the image-url("bg.png") with url(<%= asset_data_uri "bg.png" %>) will work without any need to change sass-rails. asset-data-uri doesn't exist as a pure Sass function so you have to use the Rails helper asset_data_uri.

这篇关于部署到子 URI 时,Rails 3.1 中的预编译资产损坏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆