为啥 Rails4 放弃了对 Gemfile 中“资产”组的支持

Posted

技术标签:

【中文标题】为啥 Rails4 放弃了对 Gemfile 中“资产”组的支持【英文标题】:Why did Rails4 drop support for "assets" group in the Gemfile为什么 Rails4 放弃了对 Gemfile 中“资产”组的支持 【发布时间】:2013-04-30 15:34:08 【问题描述】:

在 Rails 3 中,专门用于在资产管道中生成资产的 gem 被正确放置在 Gemfile 的 assets 组中:

...

# Gems used only for assets and not required
# in production environments by default.
group :assets do
  gem 'sass-rails'
  gem 'coffee-rails'
  gem 'uglifier'

  # See https://github.com/sstephenson/execjs#readme for more supported runtimes
  # gem 'therubyracer', :platforms => :ruby
end

现在,根据(仍在进行中)upgrade documentation:

Rails 4.0 从 Gemfile 中删除了资产组。升级时,您需要从 Gemfile 中删除该行。

果然,使用 RC1 创建一个新项目会生成一个 Gemfile,其中包含默认包含在任何组之外的资产相关 gem:

source 'https://rubygems.org'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.0.0.rc1'

# Use sqlite3 as the database for Active Record
gem 'sqlite3'

# Use SCSS for stylesheets
gem 'sass-rails', '~> 4.0.0.rc1'

# Use Uglifier as compressor for javascript assets
gem 'uglifier', '>= 1.3.0'

# Use CoffeeScript for .js.coffee assets and views
gem 'coffee-rails', '~> 4.0.0'

# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# gem 'therubyracer', platforms: :ruby

...

这是否意味着这些 gem 现在将默认捆绑在生产版本中?如果是这样,为什么会改变主意? Rails 4 是否正在朝着在生产环境中动态生成资产的方向发展?

【问题讨论】:

我仍然不明白“资产组”的目的是什么,以及 Rails 4 中的哪些变化使得资产组变得不必要。 “资产组”对不同的人来说是不同的东西。我把它用作放置我不需要捆绑在生产中的宝石的地方。但从与已接受答案相关的对话来看,至少 Rails 核心中的一些人将其用作确保非预编译资产在生产中失败并出现 404 的方式(而不是静默自动生成,这会导致不良表现)。改变的是 rails4 不再自动生成资产,因此“资产组”解决方法(正如 rails 核心看到的那样)已被删除。 这是迄今为止最清楚的解释。如果你把它放在答案中,赏金就是你的。 @MichieldeMare 我会为自己的问题获得赏金感到很奇怪;-) 如果您愿意,可以将赏金提供给 Filipe Giusti(公认的答案),因为他在帮助方面发挥了重要作用我明白了。 对未来人们的警告:如果您选择忽略 Rails 升级指南并将资产组保留在 Gemfile 中,请记住 Rails 在编译资产时将不再自动需要资产组在生产中。您需要自己执行此操作,或者在命令前添加RAILS_GROUPS=assets(请参阅Rails.groups)以在您的构建环境中预编译生产中的资产。 【参考方案1】:

以前存在资产组是为了避免在生产环境中出现意外的按需编译。由于 Rails 4 的行为不再那样,因此删除资产组是有意义的。

the commit 对此进行了更详细的解释,这改变了这一点。我提取了一些带有实际答案的引号。

如果您使用的是咖啡模板,则可能需要一些宝石(在生产中),例如咖啡轨 以及现在资产不再在生产中按需预编译的事实。

(不是在生产环境中按需预编译)意味着如果您在 3.2.x 的生产环境中拥有这些 gem 而忘记预编译,Rails 将完全按照它在开发中所做的那样,预编译所请求的资产。这在 Rails 4 中不再适用,因此如果您不使用任务预编译资产,当资产被请求时,您将得到 404。

【讨论】:

不是也节省内存吗?现在所有的 gem,即使是那些在“生产”中不需要的(仅在预编译中),都被加载了,因此 rails 会消耗更多的内存? +1 @gucki 和加载时间。这是我对组的理解。因为已经有一个配置选项可以禁用实时编译。这里的“支持”是什么意思。 afaik 我的 Rails 3 应用程序在 env/prod.rb 中有一行,它在开发时加载了资产。如果仅此而已,我们可以添加它吗? 资产组被移除。早些时候资产中的 gems 被加载到生产环境中,现在如果我们在生产环境中也需要它们怎么办。因此,它们应该在生产中加载,删除资产组可以确保这一点。资产必须在投入生产之前进行预编译。【参考方案2】:

Rails 4 试图强制您在部署之前预编译资产。您必须使用

预编译您的资产
$ RAILS_ENV=production bundle exec rake assets:precompile

为什么? 我在指南中找到了这个:

默认情况下,Rails 假定资产已经预编译,并将被 由您的网络服务器用作静态资产。

(来源:http://edgeguides.rubyonrails.org/asset_pipeline.html#in-production)

但是很多时候您必须在生产环境中使用这些“资产”gem...例如,如果您在视图目录中使用 js.coffee 文件,那么 Rails 也需要在生产模式下使用咖啡编译器。

所以我想,这种变化的原因是性能提升......而且看起来也更简单。 :)

【讨论】:

Rails 假设资产已被预编译是保留 assets 组的一个论据,而不是摆脱它(如果资产是预编译的,那么这些 gem 不是生产中需要,不应包含在捆绑器中)。是的,也许你会在生产中使用像coffee-rails 这样的宝石......但在 Rails 3 中也是如此,对吧? Rails 3 默认将coffee-rails 放在assets 组中。那么为什么要更改 Rails 4 呢? 为什么要在视图目录中使用 js.coffee 文件?这应该放在 assets/javascripts 中。【参考方案3】:

我们想要使用 AJAX (history) 的咖啡脚本,因此 coffee-rails 移出资产组。sass-rails 行为不端 (history),因此它移出资产组。

砍掉资产组。

【讨论】:

CoffeeScript 不应出现在视图中。没有它你也可以做 Ajax。您不需要动态生成 JS 来执行 Ajax。事实上,你不应该动态生成 JS。预编译你的 CoffeeScript 文件并完全避免这个问题。 sass-rails 行为不端,因为 Bundler.require :assets 没有运行。这不是删除资产组的理由。我不想要 therubyracer、libv8 等。在生产中,为什么有人这样做?咖啡模板可以编译成 JS 模板,每次替换一个新值都没有编译的意义。将所有这些负担带到生产中是没有意义的。

以上是关于为啥 Rails4 放弃了对 Gemfile 中“资产”组的支持的主要内容,如果未能解决你的问题,请参考以下文章

Rails4:为啥 resque 工人不找工作

Heroku、Rails 4 和 Rack::Cors

您想告诉我为啥即使我将 bundler 更新为“2.2.21”,Gemfile.lock 中的 bundler 版本仍然是“2.2.16”吗?

Rails 4:为啥在生产中没有加载字体?

严重困惑:ActiveMQ 是不是放弃了对连接池的支持?

为啥 onclick 在 Rails4 和 coffeescript 中的 turbolinks 的第二页请求上不起作用?