使用Bundler和Rails 4从生产中移除开发瑰宝 [英] Remove development gems from production with Bundler and Rails 4

查看:137
本文介绍了使用Bundler和Rails 4从生产中移除开发瑰宝的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题

我们部署的应用程序具有开发依赖关系.我们有很多开发依赖项.这会增加工件的大小和生产中的内存消耗,因为所有这些依赖项都被require了.大多数实例都部署在云中,因此更多的内存=较大的实例需要更多的资金.我们希望减少大小/内存,并在部署的工件和开发环境之间进行更清晰的区分.即使我们的资产是预先编译的,在生产环境中对therubyrhino的需求仍是一个特别的重点.

上下文

此问题具有一些极高评价的问相同问题的评论(请参见这一个),但实际上我看不到任何答案.

查看此处,并且似乎没有解决这个问题-我们如何从生产环境中摆脱开发依赖关系?特别是一个用户总结了相同的问题这里

仍然让我感到震惊的是,在生产中使用诸如therubyracer之类的东西时默认情况下的内存膨胀很差,特别是如果预编译是核心的建议以及目前广泛采用的最佳实践的话.很多人可能永远不会停止认为这是发生在资产组删除之后来到Rails或从未为实现该目的而进行过多考虑的情况-至少在生成的Gemfile中提出建议可能是个好主意. >

现在,对于开发人员来说,解决他们所知道的宝石(在生产网络或工作流程中不需要)是很麻烦的,因为从预编译任务中删除了加载组.我现在基本上将其作为样板添加到新的应用程序中: namespace :assets do # Override sprockets-rails task to put back assets group require, so as to # avoid memory bloat in web processes :-/ task :environment do Bundler.require(:assets) Rake::Task['environment'].invoke end end
加上将Bundler.require(*Rails.groups(assets: %w[development test]))恢复到config/application.rb.真是一团糟.

仅供参考,du在我的计算机上将therubyracer报告为17MB,并且不使用自动加载功能.我们没有使用任何CoffeeScript视图模板.

该评论的作者提出了一种解决方法,但后来在线程中使用该策略讨论了缺陷,这使我感到紧张.

tl; dr:

我们如何从生产运行时中删除开发依赖项?另外,我为什么缺少此功能/默认功能又缺少什么呢?

解决方案

如何从生产运行时删除开发依赖项?

您在引用的线程中

此注释中包含有关启用指令的说明旧的:assets小组行为:

config/application.rb中将Bundler.require(*Rails.groups)更改为Bundler.require(*Rails.groups(assets: %w[development test])),并将其添加到您的rake任务中:

namespace :assets do
  # Override sprockets-rails task to put back assets group require, so as to
  # avoid memory bloat in web processes :-/
  task :environment do
    Bundler.require(:assets)
    Rake::Task['environment'].invoke
  end
end

或者,我为什么缺少此功能/默认功能的原因,我还缺少什么?

因此,严格来说,这些不是开发依赖项.您实际上不应该这样想,因为资产预编译应该在生产环境中进行,即使只是在部署期间也是如此.您绝对不应该在开发人员计算机上进行预编译.

最重要的是,自资产管道的早期版本以来,资产专用的宝石与生产宝石之间的界线变得更加模糊.例如,许多宝石现在都希望可以使用javascript解释器.另外,现在许多Rails应用程序都在视图中使用了.coffee模板(而不是.js.erb),并且由于无法进行预编译,因此必须在生产环境中使用coffeescript.

基本上,随着Rails贡献者开始从:assets组中删除越来越多的宝石,他们意识到它真的不再需要了,并且如果它消失了将简化事情.它只是最初存在,以避免不必要的按需编译,但是资产管道在Rails 4中进行了更新,以期望默认情况下仅服务于静态资产.

最后,这可能不是最适合内存的决定(因为您正在require从未使用过的一堆宝石),但这是最通用的.

也请参考此问题有关此问题的更多讨论/答案.

Problem

Our deployed application has development dependencies in it. We have a lot of development dependencies. This increases the artifact size and the memory consumption in production, as all those dependencies are require'd. Most instances are deployed in the cloud, so more memory = more money for larger instances. We would like to reduce the size/memory and make a more clear separation between the deployed artifact and the development environment. A particular focus is the need for therubyrhino in production environments even though our assets are precompiled.

Context

This question has some extremely highly upvoted comments that are asking the same thing (see this one and this one), but I don't actually see any answers.

Looking at the Rails upgrade guide, the following is suggested:

As well, asset precompilation is done with the following command:
RAILS_ENV=production rake assets:precompile

As discussed in the linked question, this means that all gems are required in production. Fundamentally this doesn't make sense to me, and I feel like I'm missing something obvious. The whole point of asset precompilation is that we're avoiding doing it in production, so this command (so far as I understand it) should be something along the lines of:
RAILS_ENV=development RAILS_ENV_TARGET=production rake assets:precompile
Or some business.

I've read the discussion on an old Rails ticket here, and it seems to leave the question unanswered - how do we get development dependencies out of the production environment? One user in particular sums up the same problem here

It still strikes me that memory-bloat-by-default with things like therubyracer in production is poor, particularly if precompiling is core's recommendation and a widely-held best practice at this point. Many people likely never stop to consider that that's even happening if they came to Rails after the assets group removal or never gave much thought to it serving that purpose -- at least a suggestive comment in the generated Gemfile might be a good idea.

It's now a yak shave for developers to work around this for gems they know are unneeded in production web or worker processes since loading the group was removed from the precompile task. I'm basically now including this as boilerplate in new apps: namespace :assets do # Override sprockets-rails task to put back assets group require, so as to # avoid memory bloat in web processes :-/ task :environment do Bundler.require(:assets) Rake::Task['environment'].invoke end end
plus restoring Bundler.require(*Rails.groups(assets: %w[development test])) to config/application.rb. What a mess.

FYI, du reports therubyracer as 17MB on my machine, and it doesn't use autoload. We're not using any CoffeeScript view templates.

The author of that comment suggests a workaround, but later on in the thread deficiencies are discussed with that strategy, which makes me nervous.

tl;dr:

How do we remove development dependencies from production run-time? Alternatively, what am I missing as to why this ability would be desirable/the default?

解决方案

How do we remove development dependencies from production run-time?

This comment in the thread you referenced has instructions for enabling the old :assets group behavior:

Change Bundler.require(*Rails.groups) to Bundler.require(*Rails.groups(assets: %w[development test])) in config/application.rb, and add this to your rake tasks:

namespace :assets do
  # Override sprockets-rails task to put back assets group require, so as to
  # avoid memory bloat in web processes :-/
  task :environment do
    Bundler.require(:assets)
    Rake::Task['environment'].invoke
  end
end

Alternatively, what am I missing as to why this ability would be desirable/the default?

So, strictly speaking, these aren't development dependencies. You shouldn't really think of them that way, because asset precompilation should happen in a production environment, even if it's just during deploy. You definitely shouldn't be precompiling on your developer machine.

On top of that, the line between asset-specific gems and production gems has become more blurred since the earlier versions of the asset pipeline. For instance, many gems now expect a javascript interpreter to be available. Also, many Rails apps now use .coffee templates in views (instead of .js.erb), and because those can't be precompiled, coffeescript must be available in production.

Basically, as rails contributors started removing more and more gems from the :assets group, they realized that it didn't really need to exist anymore, and would simplify things if it just went away. It had only existed in the first place so to avoid unintended compilation-on-demand, but the asset pipeline was updated in Rails 4 to expect to serve only static assets by default.

In the end it may not have been the most memory-optimal decision (since you're requireing a bunch of gems you don't ever use) but it was the most universally compatible.

Edit: Also refer to this question for more discussion/answers to this question.

这篇关于使用Bundler和Rails 4从生产中移除开发瑰宝的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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