124

I'm trying to put my app into production and image and css asset paths aren't working.

Here's what I'm currently doing:

  • Image assets live in /app/assets/images/image.jpg
  • Stylesheets live in /app/assets/stylesheets/style.css
  • In my layout, I reference the css file like this: <%= stylesheet_link_tag "styles", media: "all", "data-turbolinks-track" => true %>
  • Before restarting unicorn, I run RAILS_ENV=production bundle exec rake assets:precompile and it succeeds and I see the fingerprinted files in the public/assets directory.

When I browse to my site, I get a 404 not found error for mysite.com/stylesheets/styles.css.

What am I doing wrong?

Update: In my layout, it looks like this:

<%= stylesheet_link_tag    "bootstrap.min", media: "all", "data-turbolinks-track" => true %>
<%= stylesheet_link_tag    "styles", media: "all", "data-turbolinks-track" => true %>
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>

The generate source is this:

<link data-turbolinks-track="true" href="/stylesheets/bootstrap.min.css" media="all" rel="stylesheet" />
<link data-turbolinks-track="true" href="/stylesheets/styles.css" media="all" rel="stylesheet" />
<script data-turbolinks-track="true" src="/assets/application-0c647c942c6eff10ad92f1f2b0c64efe.js"></script>

Looks like Rails is not properly looking for the compiled css files. But it's very confusing why it's working correctly for javascripts (notice the /assets/****.js path).

New Alexandria
  • 6,951
  • 4
  • 57
  • 77
emersonthis
  • 32,822
  • 59
  • 210
  • 375
  • Can you tell us how you load your css file ? It seems from your error that you try to hardlink it rather than using `stylesheet_link_tag`. – kik Sep 09 '13 at 14:22
  • 1
    Just added above. I'm doing `<%= stylesheet_link_tag "style", media: "all", "data-turbolinks-track" => true %>` – emersonthis Sep 09 '13 at 14:23
  • Ok, so I would recommand two things : 1. check in generated source if this line is written as path to `public/assets` and 2. double check if there's not an other instruction somewhere trying to load that css file (presumably hard-coded) – kik Sep 09 '13 at 14:24
  • I can't say if using .erb is a problem because I never do so : `.home {background: #FFF url(<%= image_path 'hippopotamus.jpg' %>) no-repeat; }` can actually be replaced in sprocket with `.home {background: #FFF url(image-path('hippopotamus.jpg')) no-repeat; }`. Maybe you can try if this helps. – kik Sep 09 '13 at 14:27
  • Are you saying that I can make that reference in my css file dynamic without adding the .erb extension? I changed it because I didn't want the link to break when I'm in development mode. – emersonthis Sep 09 '13 at 14:31
  • is styles in your list of things to precompile? the non-erb image-path helper will only work if you use sass – Frederick Cheung Sep 09 '13 at 14:42
  • Aha! Where is that list? This sounds like my problem. – emersonthis Sep 09 '13 at 14:50
  • "Are you saying that I" => Indeed, sprocket allows to use [dynamic methods to retrieve asset paths](http://guides.rubyonrails.org/asset_pipeline.html#css-and-sass) – kik Sep 09 '13 at 14:55
  • (the list you look for is in `config/application.rb`, as `config.assets.precompile`, but this should only be used in the precompile task, not for development resolving) – kik Sep 09 '13 at 14:56
  • In `config/application.rb`? Not `config/environments/production.rb`? – emersonthis Sep 09 '13 at 15:01
  • `config/application.rb` has one module named after my app, and a inside is `class Application < Rails::Application` but the class is empty. THe `config/environments/production.rb` has a lot of other `config.*** = true ` entries. – emersonthis Sep 09 '13 at 15:04
  • @OlivierElMekki I tried with `.home {background: #FFF url(image-path 'hippopotamus.jpg') no-repeat; }` in the .css file (no .erb) and the style rule gets ignored. Is there something else I would need to do to configure that? – emersonthis Sep 09 '13 at 15:11
  • Yes, like Frederick mentionned, it should be a sass preprocessed file. So, you have to use extension `.css.sass`, or more simply `.sass`. – kik Sep 09 '13 at 15:24
  • @OlivierElMekki I see. I'll try that. Right now I'm still stuck on getting the css files to get loaded. I went edited the question to consolidate the updates into the current state of affairs. Basically, I'm still missing some sort of configuration to get my compiled css files to get loaded in production. The mysterious part is that javascripts are working perfectly with nothing. – emersonthis Sep 09 '13 at 15:30
  • Following [this answer](http://stackoverflow.com/a/8778022/14558) I found that the problem was that `sprockets` was not in the auto-generated Gemfile so was not getting loaded in production. Fixing that made it work. – andrewdotn Apr 03 '14 at 15:19

18 Answers18

107

In rails 4 you need to make the changes below:

config.assets.compile = true
config.assets.precompile =  ['*.js', '*.css', '*.css.erb'] 

This works with me. use following command to pre-compile assets

RAILS_ENV=production bundle exec rake assets:precompile

Best of luck!

hd1
  • 33,938
  • 5
  • 80
  • 91
Rameshwar Vyevhare
  • 2,699
  • 2
  • 28
  • 34
  • 13
    I thought setting config.assets.compile to true will kill performance in production. also, css.erb? who uses that? and what about sass and coffee? – ahnbizcad Aug 31 '14 at 13:48
  • when coffee and sass files are requested, they are processed by the processors provided by the coffee-script and sass-rails gems and then sent back to the browser as JavaScript and CSS respectively. – Rameshwar Vyevhare Sep 01 '14 at 16:27
  • "turbo-sprockets-rails3" gem to Speeds up your Rails 3 assets:precompile by only recompiling changed files, and only compiling once to generate all assets, this will answer your first question. – Rameshwar Vyevhare Sep 01 '14 at 16:38
  • 1
    This issue already solved for Rails 4 and so no need to use turbo-sprocket-rails3 gem – Rameshwar Vyevhare Sep 01 '14 at 16:42
  • 4
    Sorry, I am not able to make the connection of what you said to answer my question. – ahnbizcad Sep 01 '14 at 18:13
  • I agree with you but that issues can be overcome using turbo-sprocket-rails3 gem. – Rameshwar Vyevhare Sep 02 '14 at 04:42
  • I think the `config.assets.precomile = ...` is unnecessary. Mine works fine without it and this `# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.` is a generated comment in the `production.rb` file. I think adding to `precompile` is for additional assets. – MCB Nov 20 '14 at 20:00
  • http://stackoverflow.com/questions/8821864/config-assets-compile-true-in-rails-production-why-not – karlingen Jan 11 '15 at 17:42
  • I agree with you but in my case there are some files in .css.erb so i used this to make sure every files get precompiled. – Rameshwar Vyevhare Jan 13 '15 at 04:33
  • 2
    Normally, when you run production server, you will run Rails with passenger or unicorn or puma behind Apache or nginx webserver. It is better to let Apache or nginx serve static files (js, css, images), and the Rails application server (puma, unicorn) serve Rails code and template. In order to do so, you should turn off `config.serve_static_files`, and configure alias in Apache and nginx to deal with `assets`. – Châu Hồng Lĩnh Jun 05 '16 at 02:16
  • Yes I already turn off, if anyone precompile set while deploying then compile = true not required.there are few people has issue with specially complex application where lots of js and css files and also have some .erb extension they suffer as thier assets not precompiled properly or not loading properly may help them making some custom ways like above. after all I'm agree with you. web server has to perform serving static jobs thats the one of the reason why app server not perform fully web server's job. – Rameshwar Vyevhare Jun 06 '16 at 06:01
  • I had several issues crippling my CSS. In addition to this step I had to do some other tweaks. Read this [answer](http://stackoverflow.com/a/39526827/1903781) if your issue still persists after precompile. – Adrian Moisa Sep 16 '16 at 11:48
89

I just had the same problem and found this setting in config/environments/production.rb:

# Rails 4:
config.serve_static_assets = false

# Or for Rails 5:
config.public_file_server.enabled = false

Changing it to true got it working. It seems by default Rails expects you to have configured your front-end webserver to handle requests for files out of the public folder instead of proxying them to the Rails app. Perhaps you've done this for your javascript files but not your CSS stylesheets?

(See Rails 5 documentation). As noted in comments, with Rails 5 you may just set the RAILS_SERVE_STATIC_FILES environment variable, since the default setting is config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?.

davmac
  • 20,150
  • 1
  • 40
  • 68
  • 1
    DEPRECATION WARNING: The configuration option `config.serve_static_assets` has been renamed to `config.serve_static_files` to clarify its role (it merely enables serving everything in the `public` folder and is unrelated to the asset pipeline). The `serve_static_assets` alias will be removed in Rails 5.0. Please migrate your configuration files accordingly. – yekta Oct 01 '15 at 08:34
  • Earlier when I was facing this problem changing that line had solved it for me, but now I'm facing it again (I don't know how I keep ending up in these situations.) and this isn't enough. Any more suggestions as to what might be wrong? – IIllIIll Nov 29 '15 at 22:45
  • 2
    This should be the accepted answer. Though it's `config.serve_static_files` in Rails *4.2* and `config.public_file_server.enabled` in Rails *5*. @see https://github.com/heroku/rails_serve_static_assets/blob/master/lib/rails_serve_static_assets/railtie.rb – Lucas Nelson Apr 06 '16 at 04:10
  • 3
    Rails 5.0.0.1 config/environments/production.rb contains `config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?` so you can set this differently for your environment without changing code that's checked in to your SCM. – tobinjim Oct 10 '16 at 11:55
  • To enable it: "export RAILS_SERVE_STATIC_FILES=" then you run "rails s -e production" To disable it: "unset RAILS_SERVE_STATIC_FILES" – Alfredo Osorio Jan 04 '18 at 21:22
33

In /config/environments/production.rb I had to add this:

Rails.application.config.assets.precompile += %w( *.js ^[^_]*.css *.css.erb )

The .js was getting precompiled already, but I added it anyway. The .css and .css.erb apparently don't happen automatically. The ^[^_] excludes partials from being compiled -- it's a regexp.

It's a little frustrating that the docs clearly state that asset pipeline IS enabled by default but doesn't clarify the fact that only applies to javascripts.

hd1
  • 33,938
  • 5
  • 80
  • 91
emersonthis
  • 32,822
  • 59
  • 210
  • 375
23

I was able to solve this problem by changing: config.assets.compile = false to
config.assets.compile = true in /config/environments/production.rb

Update (June 24, 2018): This method creates a security vulnerability if the version of Sprockets you're using is less than 2.12.5, 3.7.2, or 4.0.0.beta8

Yanofsky
  • 1,806
  • 1
  • 17
  • 15
17

For Rails 5, you should enable the follow config code:

config.public_file_server.enabled = true

By default, Rails 5 ships with this line of config:

config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?

Hence, you will need to set the environment variable RAILS_SERVE_STATIC_FILES to true.

ytbryan
  • 2,644
  • 31
  • 49
  • 1
    For Rails 5, I should add, I set `passenger_env_var RAILS_SERVE_STATIC_FILES true;` in the location block of my app in my nginx.conf file. – Martin Velez Feb 24 '17 at 09:35
10

There are 2 things you must accomplish to serve the assets in production:

  1. Precompile the assets.
  2. Serve the assets on the server to browser.

1) In order to precompile the assets, you have several choices.

  • You can run rake assets:precompile on your local machine, commit it to source code control (git), then run the deployment program, for example capistrano. This is not a good way to commit precompiled assets to SCM.

  • You can write a rake task that run RAILS_ENV=production rake assets:precompile on the target servers each time you deploy your Rails app to production, before you restart the server.

Code in a task for capistrano will look similar to this:

on roles(:app) do
  if DEPLOY_ENV == 'production'
    execute("cd #{DEPLOY_TO_DIR}/current && RAILS_ENV=production rvm #{ruby_string} do rake assets:precompile")
  end
end

2) Now, you have the assets on production servers, you need to serve them to browser.

Again, you have several choices.

  • Turn on Rails static file serving in config/environments/production.rb

    config.serve_static_assets = true # old
    
    or
    
    config.serve_static_files = true # new
    

    Using Rails to serve static files will kill your Rails app performance.

  • Configure nginx (or Apache) to serve static files.

    For example, my nginx that was configured to work with Puma looks like this:

    location ~ ^/(assets|images|fonts)/(.*)$ {
        alias /var/www/foster_care/current/public/$1/$2;
        gzip on;
        expires max;
        add_header Cache-Control public;
    }
    
Châu Hồng Lĩnh
  • 1,986
  • 1
  • 20
  • 23
4

Rails 4 no longer generates the non fingerprinted version of the asset: stylesheets/style.css will not be generated for you.

If you use stylesheet_link_tag then the correct link to your stylesheet will be generated

In addition styles.css should be in config.assets.precompile which is the list of things that are precompiled

Frederick Cheung
  • 83,189
  • 8
  • 152
  • 174
  • I see the fingerprinted file in the /public/assets/ directory. In my layout, I have this: `<%= stylesheet_link_tag "styles", media: "all", "data-turbolinks-track" => true %>` Is this incorrect?` – emersonthis Sep 09 '13 at 14:21
  • For some reason, the production deployment is still pointing to the original files when I view the source `` But the the javascript files are correct! I don't understand why the same configurations work for .js files but not .css. – emersonthis Sep 09 '13 at 15:23
  • On Rails 5.0.0.beta3 I get this warning: DEPRECATION WARNING: `serve_static_files` is deprecated and will be removed in Rails 5.1. Please use `public_file_server.enabled = true` instead. – GMA Mar 08 '16 at 15:52
  • @emersonthis Same! Js loads perfectly but some css files get `404`. Did you resolve this? – IvRRimUm Apr 10 '17 at 14:35
  • It's almost ALWAYS a problem with asset pipeline configuration. If you have files in any location that isn't default, that's almost definitely the issue and you need to tell the asset pipeline about it using something like the first answer. – emersonthis Apr 12 '17 at 01:04
3

change your Production.rb file line

config.assets.compile = false

into

config.assets.compile = true

and also add

config.assets.precompile =  ['*.js', '*.css', '*.css.erb']
3

What you SHOULD NOT do:

Some of my colleagues above have recommended you to do this:

config.serve_static_assets = true  ## DON”T DO THIS!! 
config.public_file_server.enabled = true ## DON”T DO THIS!!

The rails asset pipeline says of the above approach:

This mode uses more memory, performs more poorly than the default and is not recommended. See here: (http://edgeguides.rubyonrails.org/asset_pipeline.html#live-compilation)

What you SHOULD do:

Precompile your assets.

RAILS_ENV=production rake assets:precompile

You can probably do that with a rake task.

BenKoshy
  • 33,477
  • 14
  • 111
  • 80
  • Why add build artefacts to the git though? You can just add rake task to your build process and avoid massive gitspam (especially if you have uglifier and gzipping on, which you should) – Dr.Strangelove Aug 17 '19 at 07:33
  • @Dr.Strangelove Thank you for your comment - I don't know enough about that - : can you elaborate / edit the original post? – BenKoshy Aug 17 '19 at 07:41
2

I'm running Ubuntu Server 14.04, Ruby 2.2.1 and Rails 4.2.4 I have followed a deploy turorial from DigitalOcean and everything went well but when I go to the browser and enter the IP address of my VPS my app is loaded but without styles and javascript.

The app is running with Unicorn and Nginx. To fix this problem I entered my server using SSH with my user 'deployer' and go to my app path which is '/home/deployer/apps/blog' and run the following command:

RAILS_ENV=production bin/rake assets:precompile

Then I just restart the VPS and that's it! It works for me!

Hope it could be useful for somebody else!

alexventuraio
  • 8,126
  • 2
  • 30
  • 35
2

If precompile is set you DO NOT need

config.assets.compile = true

as this is to serve assets live.

Our problem was we only had development secret key base set in config/secrets.yml

development:
    secret_key_base: '83d141eeb181032f4070ae7b1b27d9ff'

Need entry for production environment

pdoherty926
  • 9,895
  • 4
  • 37
  • 68
xxjjnn
  • 14,591
  • 19
  • 61
  • 94
  • 1
    as mentioned in other answers you need `config.assets.precompile = ['*.js', '*.css', '*.css.erb'] ` and to run `RAILS_ENV=production bundle exec rake assets:precompile` – xxjjnn Oct 16 '15 at 12:41
  • 1
    this enable compilation of assets while live on production, very slow, not right – James Tan Sep 19 '16 at 16:35
1

The default matcher for compiling files includes application.js, application.css and all non-JS/CSS files (this will include all image assets automatically) from app/assets folders including your gems:

If you have other manifests or individual stylesheets and JavaScript files to include, you can add them to the precompile array in config/initializers/assets.rb:

Rails.application.config.assets.precompile += ['admin.js', 'admin.css', 'swfObject.js']

http://guides.rubyonrails.org/asset_pipeline.html#precompiling-assets

Community
  • 1
  • 1
FreePender
  • 4,770
  • 2
  • 18
  • 15
1

First of all check your assets, it might be possible there is some error in pre-compiling of assets.

To pre-compile assets in production ENV run this command:

RAILS_ENV=production rake assets:precompile

If it shows error, remove that first,

In case of "undefined variable" error, load that variable file before using it in another file.

example:

@import "variables";
@import "style";

in application.rb file set sequence of pre-compiliation of assets

example:

config.assets.precompile += [ 'application.js', 'admin.js', 'admin/events.js', 'admin/gallery.js', 'frontendgallery.js']

config.assets.precompile += [ 'application.css', 'admin.css','admin/events.css', 'admin/gallery.css', 'frontendgallery.css']
Chitresh goyal
  • 313
  • 1
  • 7
1

Found this:

The configuration option config.serve_static_assets has been renamed to config.serve_static_files to clarify its role.

in config/environments/production.rb:

# Disable serving static files from the `/public` folder by default since
# Apache or NGINX already handles this.
config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present?

So set env RAILS_SERVE_STATIC_FILES or using Nginx to serving static files. Add config.serve_static_assets = true will still work, but removed in future.

Daniel Wei
  • 619
  • 1
  • 8
  • 12
1

it is not recommended to let capistrano do assets precompile, because it may take ages and often time out. try to do local assets precompile.

1st, set in config/application.rb config.assets.initialize_on_precompile = false then do local RAILS_ENV=production bin/rake assets:precompile and add those public/assets to git.

and config/environments/development.rb, change your asset path to avoid using precompiled assets:

config.assets.prefix = '/dev-assets'

If you have db connection issue, means u have initializer that uses db. one way around it is to set a new environment by duplicate production.rb as maybe production2.rb, and in database.yml, add production2 environment with development db setting. then do

RAILS_ENV=production2 bin/rake assets:precompile

if you are still facing some issue with assets, for example ckeditor, add the js file into config/initializers/assets.rb

Rails.application.config.assets.precompile += %w( ckeditor.js )

James Tan
  • 1,336
  • 1
  • 14
  • 32
0

I may be wrong but those who recommend changing

config.assets.compile = true

The comment on this line reads: #Do not fallback to assets pipeline if a precompiled asset is missed.

This suggests that by setting this to true you are not fixing the problem but rather bypassing it and running the pipeline every time. This must surely kill your performance and defeat the purpose of the pipeline?

I had this same error and it was due to the application running in a sub folder that rails didn't know about.

So my css file where in home/subfolder/app/public/.... but rails was looking in home/app/public/...

try either moving your app out of the subfolder or telling rails that it is in a subfolder.

Brad
  • 8,044
  • 10
  • 39
  • 50
0
location ~ ^/assets/ {
  expires 1y;
  add_header Cache-Control public;
  add_header ETag "";
}

This fixed the problem for me in production. Put it into the nginx config.

0

Even we faced the same problem where RAILS_ENV=production bundle exec rake assets:precompile succeeded but things did not work as expected.
We found that unicorn was the main culprit here.

Same as your case, even we used to restart unicorn after compiling the assets. It was noticed that when unicorn is restarted, only its worker processes are restarted and not the master process.
This is the main reason the correct assets are not served.

Later, after compiling assets, we stopped and started unicorn so that the unicorn master process is also restarted and the correct assets were getting served.
Stopping and starting unicorn brings around 10 secs on downtime when compared to restarting the unicorn. This is the workaround that can be used where as long term solution is move to puma from unicorn.

goto
  • 7,908
  • 10
  • 48
  • 58