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 restoringBundler.require(*Rails.groups(assets: %w[development test]))
toconfig/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?