3

Just a ponder. If you compile assets with asset_sync gem and do not fallback to have sprockets compile on runtime can you remove the app/assets folder from your slug using .slugignore to reduce slug size?

I've tested and the precompiled assets are not longer served using asset pipeline. Rails must look for the app/assets folder and gets grumpy if it's not available, defaulting to on-demand compilation.

Anyone else tried anything to this effect? The only thing I've found is that build backs are called after slug-ignore so if I'm using the turbo sprockets it might muck up the caching between deploys.

jhblacklock
  • 146
  • 9
  • I haven't tried to do this, but I believe that precompiled assets on Heroku are stored in `/public/assets`, which is in the asset pipeline... This is an interesting idea, though. – CDub Nov 18 '13 at 23:30
  • Good point CDub. That means that there are two sources of assets that are essentially dead weight. If we are serving all assets from an asset host then the app/assets folder and public/assets folder are never accessed. – jhblacklock Nov 19 '13 at 14:49
  • Bingo. Having slept on this, I'm thinking maybe if you do `rake assets:precompile` *before* you deploy, you could ignore all asset pipeline on deploy to Heroku… Thoughts? – CDub Nov 19 '13 at 14:50
  • I was on the same page but I realized it might be easier to just destroy all assets with a post compile hook. – jhblacklock Nov 19 '13 at 17:46
  • I'm not sure that's possible to do with Heroku hooks. If you can, I'd love to know how. – CDub Nov 19 '13 at 17:47

2 Answers2

3

this post has a great solution for this with a post precompile task. I modified it to remove everything, including the app/assets files. It might be a bit drastic for some folks but it's a simple way to cut some cruft.

This reduced my slug size by 20mb.

Rake::Task["assets:precompile"].enhance do
  return "can't run in dev" if Rails.env.development?
  puts 'my assets:precompile hook is started!'
  ["#{Dir.pwd}/public/", "#{Dir.pwd}/app/assets/"].each do |dir_path|
    records = Dir.glob("#{dir_path}**/*")
    records.each do |f|
      if f =~ /.*.png$/ or
        f =~ /.*.jpg$/ or
        f =~ /.*.gif$/ or
        f =~ /.*.ico$/ or
        f =~ /.*.eot$/ or
        f =~ /.*.svg$/ or
        f =~ /.*.woff$/ or
        f =~ /.*.ttf$/ or
        f =~ /.*.otf$/ or
        f =~ /.*.css$/ or
        f =~ /.*.js$/ or
        f =~ /.*.sass$/ or
        f =~ /.*.css$/ or
        f =~ /.*.scss$/ or
        f =~ /.*.coffee$/ or
        f =~ /.*.wav$/ then
        File.delete(f)
        puts "removing #{f}"
      end
    end
    puts Dir.glob("#{dir_path}**/*")
  end
  puts 'my assets:precompile hook is finished!'
end
Community
  • 1
  • 1
jhblacklock
  • 146
  • 9
3

There are a lot of reasons that the slug size is too large. 3 of the most common are:

  • Extra/Unused Gems
  • Tmp Cacheing
  • Large assets through .slugignore

I spent about 3 hours going through all of the possibilities of why my slug size was too large.

All of the gems I have in my gem file I need, so that's out. I tried using a .slugignore via https://devcenter.heroku.com/articles/slug-compiler and that helped a little bit.

The final solution for me was ignoring assets from other environments.

To do this, open application.rb and add:

config.assets.configure do |env| if Rails.env.development? || Rails.env.test? env.cache = ActiveSupport::Cache.lookup_store(:memory_store)

This will ignore any extra cacheing that is getting pulled in from other environments. If you are deploying to heroku, before you precompile, run: heroku config:set BUNDLE_WITHOUT="development:test". After, run your regular git push heroku master.

If you look back in the log, you will notice that it skipped right over development and test. This reduced my slug size by over 50mb. I hope this helps somebody!

Stephen Burke
  • 389
  • 2
  • 13