77

Everything goes well in local machine with assets pipeline in Rails 4 and Ruby 2.0. But when deploying to heroku, it is shown that:

-----> Preparing app for Rails asset pipeline
   Running: rake assets:precompile
   I, [2013-03-12T03:28:29.908234 #912]  INFO -- : Writing /tmp/build_1n6yi8lwna3sj/public/assets/rails-2ee5a98f26fbf8c6c461127da73c47eb.png
   I, [2013-03-12T03:28:29.914096 #912]  INFO -- : Writing /tmp/build_1n6yi8lwna3sj/public/assets/trash-3c3c2861eca3747315d712bcfc182902.png
   I, [2013-03-12T03:28:33.963234 #912]  INFO -- : Writing /tmp/build_1n6yi8lwna3sj/public/assets/application-bf2525bd32aa2a7068dbcfaa591b3874.js
   I, [2013-03-12T03:28:40.362850 #912]  INFO -- : Writing /tmp/build_1n6yi8lwna3sj/public/assets/application-13374a65f29a3b4cea6f8da2816ce7ff.css
   Asset precompilation completed (14.36s)

Heroku seems to compile files but put it in /tmp without any errors. My questions are:

  1. How come Heroku compile assets files to /tmp?
  2. My last solution was to run RAILS_ENV=production bundle exec rake assets:precompile locally, but this generated a manifest-xxxxxx.json in public/assets, rather than manifest.yml, so that heroku doesn't detect the JSON manifest file. I sorted it out by manually created a yml from the json file and heroku became happy. Has heroku's approach been outdated?
Manuel Pedrera
  • 5,347
  • 2
  • 30
  • 47
aquajach
  • 2,548
  • 2
  • 23
  • 29
  • 1) someone is looking into this – catsby Mar 12 '13 at 21:53
  • 2) that changed in rails 4, there's a pull request to the buildpack to update it – catsby Mar 12 '13 at 21:53
  • There's https://github.com/heroku/heroku-buildpack-ruby/pull/74 for the manifest issue. I'll bug people about the /tmp/ issue today, still happening right? – catsby Mar 18 '13 at 16:26
  • @ctshryock Yes, unfortunately it is still happening... Thanks for the proper contribution... – Boti Mar 20 '13 at 10:15
  • My pull request has been merged, but a new release hasn't been cut. You can specify the buildpack manually in your ENV if you need. – catsby May 08 '13 at 20:29
  • @aquajach a new version of the buildpack has been released with my pull request in it, so it should detect your manifest file correctly now – catsby May 21 '13 at 14:40
  • I've just added a very simple fix that works with Rails 4. – Evolve Nov 11 '14 at 00:52

16 Answers16

102

Heroku's asset plugins no longer work since Rails 4 does not support plugins. You need to use Heroku's asset gems instead. Place this in your Gemfile:

group :production do
  gem 'rails_log_stdout',           github: 'heroku/rails_log_stdout'
  gem 'rails3_serve_static_assets', github: 'heroku/rails3_serve_static_assets'
end

Follow Heroku's guide on getting started with Rails 4.

Update (07/22/2013): Heroku now supplies a different gem to precompile assets.

group :production do
  gem 'rails_12factor'
end
Community
  • 1
  • 1
Joseph Ravenwolfe
  • 6,480
  • 6
  • 31
  • 31
  • 14
    This wasn't necessary for me. Just had to follow @Israel Barba's answer to change `config.serve_static_assets = false` to `true`. – Matt De Leon Jun 17 '13 at 18:13
  • 2
    I previously had done it that way, but I believe if you do it that way you have to precompile the assets and commit them yourself. Is that still correct? – Joseph Ravenwolfe Jun 18 '13 at 14:21
  • It worked without precompiling. There may be a scenario where it doesn't work that I'm not catching (I only had one simple stylesheet) – Matt De Leon Jun 18 '13 at 15:46
  • 2
    This does not work. Neither does precompiling. For us the asset pipeline is broken on heroku for rails 4 and we wasted massive time, back to ec2 - grumble grumble. – Joshua Kolden Aug 15 '13 at 18:22
  • @JoshuaKolden, Are you using specific gems that are not working? Rails 4 also introduces a change that requires gems to place assets in their own assets directory and add them to the asset pipeline. It might be that the gem you are using hasn't been updated for this. – Joseph Ravenwolfe Aug 16 '13 at 14:16
  • Nothing fancy just regular scss. Works for application wide sass, but controller specific scss does not work, regardless of where it's compiled. – Joshua Kolden Aug 17 '13 at 21:21
  • Any update on this? I'm having the same problem. My assets aren't being served :[ – sizzle Aug 21 '13 at 20:38
  • 4
    Are you using the asset_path() helper in your CSS and elsewhere? Referencing assets via "/assets/filename.jpg" will also not work on Heroku. – Joseph Ravenwolfe Aug 22 '13 at 14:56
33

You need to config Rails to serve static assets in production: config/environments/production.rb

SampleApp::Application.configure do
  .
  .
  .
  config.serve_static_assets = true
  .
  .
  .
end

UPDATE:

In Rails 4 is deprecated, and has been changed by:

config.serve_static_files = true 
Israel Barba
  • 1,434
  • 20
  • 28
  • 1
    I also had to remove my public/assets folder, because those were precompiled locally by someone else on my team, checked into GitHub and overwritting Heroku's asset compiling process. – user1515295 Nov 30 '15 at 00:47
16

Since rails 4 replaced manifest.yml with manifest-(fingerprint).json, you'll want to enable static asset serving.

From Getting Started with Rails 4.x on Heroku:

gem 'rails_12factor', group: :production

then

bundle install

and, finally,

git push heroku

Fixed the issue for me. Hope this helps!

voss
  • 161
  • 1
  • 5
  • 1
    this is what they say on the official document, but does it work for other people? I had this on my gemfile and the javascript files still seemed they werent precompiled – Maximus S Jul 03 '13 at 08:32
  • 1
    I have done everything: gem 'rails_12factor', group: :production config.serve_static_assets = true config.assets.precompile += %w( *.css *.js ) I have my js and css files under vendor/assets/. When I deploy to heroku everything looks good: Running: rake assets:precompile Asset precompilation completed (310.44s) When I see application-5c84e59d83c00fd13fb659edc18db24a.js, it is all empty Do you know what I'm doing wrong ? – Alexander Giraldo Jul 12 '13 at 21:13
  • This did not work for me. `config.serve_static_assets = true` meant that the css started serving correctly, but not the images or JS. – Alex Lynham Jul 15 '13 at 22:49
  • This worked for me, thanks @voss for the updated answer. Heroku has replaced rails_log_std_out and rails3_serve_static_assets with rails_12factor. – Aaron Gray Jul 27 '13 at 16:57
  • how are you referencing your images? I've tried background-image:url('/public/assets/starsw600.jpg'); and just ('starsw600.jpg'). Have not tried all combinations with config.serve_static_assets and ('starsw60xxxxxx.jpg). – flobacca Nov 14 '13 at 01:45
  • "If you are starting a new application with Rails 5, you do not need this gem" - rails_12factor github https://github.com/heroku/rails_12factor#rails-4-serve-static-assets – Abel Sep 25 '17 at 02:16
14

I run exactly into the same problem.

I set config.serve_static_assets = true in my environments/production.rb file until heroku wont't support the new manifest format.

So it is a temporal solution until heroku support will be added.

Boti
  • 3,275
  • 1
  • 29
  • 54
  • that doesn't work. Heroku injects _[this](https://github.com/pedro/rails3_serve_static_assets/blob/master/init.rb)_ that does exactly that : i.e. it won't work, best solution so far : copy the manifest.json to manifest.yml (no converting needed) to trick heroku into detecting precompiled assets. – dakull May 10 '13 at 13:53
  • 5
    If you serve static assets, it will work, but it will not work for all of the gems that have assets of their own, like Font Awesome or HTML5 Boilerplate. – Joseph Ravenwolfe May 15 '13 at 16:50
  • @dakull that worked in that it now correctly serves the JS files, but the background image textures in the `app/assets/images` directory are still not being served. – Alex Lynham Jul 15 '13 at 22:57
13

After hours of googling in which none of the guides on Heroku or the suggestions on StackOverFlow helped me, I finally ran into this blog post which offered this clue:

heroku labs:enable user-env-compile --app=YOUR_APP

Without this, the asset pipeline will always try to init the whole app and connect to the database (despite all the things you may have read that rails 4 now longer does this). This exposes your Heroku configuration to Rails so it can boot up successfully and run rake tasks like assets:precompile.

PatrickEm
  • 346
  • 2
  • 10
7

I needed to use this gem:

gem 'rails_12factor', group: :production #need this for rails 4 assets on heroku

And in /config/environments/production.rb I needed to set:

config.assets.compile = true

My understanding is that the rails_12_factor gem sets config.serve_static_assets = true, amongst other things.

wuliwong
  • 4,238
  • 9
  • 41
  • 69
4

In my case, assets compiled following the instructions above but it wasn't picking the bootstrap glyphicons 'fontawesome-webfont' so this worked for me finally after wasting so many hours researching.

Gem file

gem 'rails_12factor', group: :production

bundle install

config/application.rb

config.assets.precompile += %w(*.png *.jpg *.jpeg *.gif,
                                  "fontawesome-webfont.ttf",
                                 "fontawesome-webfont.eot",
                                 "fontawesome-webfont.svg",
                                 "fontawesome-webfont.woff")



config.assets.precompile << Proc.new do |path|
      if path =~ /\.(css|js)\z/
        full_path = Rails.application.assets.resolve(path).to_path
        app_assets_path = Rails.root.join('app', 'assets').to_path
        if full_path.starts_with? app_assets_path
          puts "including asset: " + full_path
          true
        else
          puts "excluding asset: " + full_path
          false
        end
      else
        false
      end
    end

environment/production.rb

config.serve_static_assets = true

Then finally, I ran rake assets:precompile RAILS_ENV=production and pushed it to heroku and that worked.

3

This was an issue with the Heroku Ruby Buildpack, but an update was deployed today (2013-05-21). Please try it out and let us know.

To answer your questions:

#1) This is sprockets output; things are compiled to /tmp and then moved (See here in Sprockets). To my knowledge this has always been done this way, but it wasn't until Sprockets version was updated in Rails that we got this new debug-type output.

#2) Previously assets:precompile genereated a manifest.json file, but now in Rails 4 the manifest file has a fingerprint in it, which wasn't detected previously. This was fixed with #74.

catsby
  • 11,276
  • 3
  • 37
  • 37
2

I added this to the top of one of my css.scss files in the assets/stylesheets/ folder.

@import "font-awesome";

then ran..

rake assets:clean

and...

rake assets:precompile RAILS_ENV=production
tuneyfish
  • 31
  • 3
2

In Rails 4.2.4 your production.rb has the line:

config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present?

That means, gem 'rails_12factor', group: :production doesn`t need to change it to true, as it can be set through the heroku environment variables. You also will get a warning if you remove the rails_12factor gem.

If you have problems with assets, login to the heroku console heroku run rails console and find out the asset path for a file puts helper.asset_path("application.js") .

One strange behaviour I noticed between development and production, when the file ending is not provided:

With a image /assets/images/image_01.jpg the following output from asset_pathsdiffers:

Development:

development > puts helper.asset_path('profile_01') 
=> /assets/profile_01-bbd16aac5ef1d295411af44c103fcc631ab90ee94957414d4c01c3aed1055714.jpg

development > puts helper.asset_path('profile_01.jpg') 
=> /assets/profile_01-bbd16aac5ef1d295411af44c103fcc631ab90ee94957414d4c01c3aed1055714.jpg

Production:

development > puts helper.asset_path('profile_01') 
=> /profile_01

development > puts helper.asset_path('profile_01.jpg') 
=> /assets/profile_01-bbd16aac5ef1d295411af44c103fcc631ab90ee94957414d4c01c3aed1055714.jpg

You do not have to run RAILS_ENV=production rake assets:precompile, heroku does this for you during deploy. Also you do not have to precompile the assets in development and push them to heroku.

neonmate
  • 509
  • 4
  • 10
1

Apart from ensuring you have the 'rails_12factor' gem installed the only thing you need to do is this.

# config/application.rb

config.assets.paths << Rails.root.join('vendor', 'assets')

It seems that although Rails knows exactly what it wants, Heroku needs reminding to include the assets folder as part of the assets paths.

Evolve
  • 8,939
  • 12
  • 51
  • 63
1

Use Image Extensions

I had this same issue, but for a different reason.

Instead of

<%= asset_path 'facebook-link' %>

Use:

<%= asset_path 'facebook-link.png' %>

While the first one worked locally, when I pushed to Heroku my images were breaking and I had no clue why. Using the full file extension fixed the problem :)

Phil
  • 2,732
  • 19
  • 20
1

Add this gem gem 'rails_serve_static_assets'

https://github.com/heroku/rails_serve_static_assets

Ben
  • 739
  • 6
  • 25
0

If you are using controller specific assets as in:

 <%= javascript_include_tag params[:controller] %> or <%= javascript_include_tag params[:controller] %>

Then in production you will need to explicitly precompile those (in development rails compiles files on the fly).

See official Rails guide here: http://guides.rubyonrails.org/asset_pipeline.html#controller-specific-assets

To precompile as explained in the guides (here: http://guides.rubyonrails.org/asset_pipeline.html#precompiling-assets) you will need to add the following to the config/application.rb

# config/application.rb
config.assets.precompile << Proc.new do |path|
  if path =~ /\.(css|js)\z/
    full_path = Rails.application.assets.resolve(path).to_path
    app_assets_path = Rails.root.join('app', 'assets').to_path
    if full_path.starts_with? app_assets_path
      puts "including asset: " + full_path
      true
    else
      puts "excluding asset: " + full_path
      false
    end
  else
    false
  end
end
Andrea
  • 143
  • 1
  • 2
  • 7
0

I figure I'll add this as an answer since this question is linked from the Heroku Support page if you search for "assets".

This is mostly for people who are updating their app to Rails 4, but after going through this - and many other SO posts - what finally got me was changing the following in production.rb:

config.action_dispatch.x_sendfile_header = "X-Sendfile"

To:

config.action_dispatch.x_sendfile_header = nil

I hadn't caught this when I upgraded and as usual this took me forever to figure out. Hopefully it helps someone else! Shout out to PatrickEm who asked/answered the same in his question.

Community
  • 1
  • 1
tvalent2
  • 4,959
  • 10
  • 45
  • 87
0

This may not answer the original question's root cause, But I was having a similar symptom with a different root cause.

Pre-compilation of a JPEG files changes the file extension to JPG, meaning that asset_path("my_image.jpeg") and asset_path("my_image") didn't work. Remove the "e" from JPEG and voila, it works.

Others have described the same problem here https://blazarblogs.wordpress.com/2016/04/06/rails-force-to-precompile-jpeg-to-jpg/

Is this a bug? Or desired behaviour? And also weird that it only doesn't work in my Heroku-hosted production environment. Maybe they have some sort of configuration.

Anthony Wood
  • 395
  • 1
  • 3
  • 16