rails - application.css asset not found in production mode
Solution 1
Rails by default doesn't serve assets under public
. See your production.rb
:
config.serve_static_assets = true
Change that to true and you're good to go. (Note: you don't want that to be true
in production, remember to change it back before deploying!)
See Configuring Rails Applications for details.
In rails 6, in the default production.rb
there should be a line
config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
So run your server with
RAILS_SERVE_STATIC_FILES=true rails server -e production
or set config.public_file_server.enabled=true
in production.rb
. See answers below for rails 4 and 5.
Solution 2
The Rails 5 solution is similar to the Rails 4 solution given by Jules Copeland above.
In your pre-generated config/environments/production.rb
file, there should be an entry that looks something like this:
# Disable serving static files from the `/public` folder by default since
# Apache or NGINX already handles this.
config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
I found a decent explanation for this setting in the Configuring Rails Applications guide at http://guides.rubyonrails.org:
config.public_file_server.enabled configures Rails to serve static files from the public directory. This option defaults to true, but in the production environment it is set to false because the server software (e.g. NGINX or Apache) used to run the application should serve static files instead. If you are running or testing your app in production mode using WEBrick (it is not recommended to use WEBrick in production) set the option to true. Otherwise, you won't be able to use page caching and request for files that exist under the public directory.
Conclusion: In production, starting your rails server with RAILS_SERVE_STATIC_FILES=1
will allow Rails to serve any files in the public/assets directory just as a web server would. Keep in mind, Rails is an app server and will not do this as efficiently as a web server (e.g. NGINX, Apache, etc.). For real-world applications, you should have a dedicated web server sitting in front of Rails which will serve static assets by itself and only bother Rails for dynamic content as needed. For more details, see this article by Justin Weiss on the differences between web servers and app servers.
Solution 3
In Rails 4, you can get them to show in production (running locally), by passing an environment variable:
RAILS_SERVE_STATIC_FILES=true rails server -e production
This should work as long as you have this line in /config/environments/production.rb
:
config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present?
Solution 4
When you do rake assets:precompile
, your assets go into public directory. See if you can find those files in public/assets/
You should see something like this:
I, [2014-02-23T20:06:21.853314 #26915] INFO -- : Writing app_root/public/assets/application-ecd8636fc80ea2b712039c4abc365da9.css
Comments
-
Michael Durrant over 3 years
I'm upgrading an application to use the asset pipeline.
I've got the css assets compiling into an application css file but they not being found when I run the application in production mode with
RAILS_ENV=production bundle exec rails s
and I visit any page I get the correct output from the database but no styling and the log shows:
ActionController::RoutingError (No route matches [GET] "/assets/default.scss-1a27c...f07c.css"):
Even though that file exists in public/assets
$ ls public/assets/def* public/assets/default.scss-1a27c...f07c.css public/assets/default.scss.css public/assets/default.scss-1a27c...f07c.css.gz public/assets/default.scss.css.gz
What do I need to change to get the server to find the asset file?
Same is happening for my other .css files. They get compiled into public/assets with finger prints but then are not found.
Page source is showing:
<link href="/assets/default.scss-1a27c...f07c.css" media="screen" rel="stylesheet" type="text/css" />
The rails (haml) source is
= stylesheet_link_tag 'default.scss.css'
public.assets
curently includes has the following files.$ ls public/assets/def* public/assets/default.scss-1a27c22229b7b522066181f27af4f07c.css public/assets/default.scss-1a27c22229b7b522066181f27af4f07c.css.gz public/assets/default.scss.css public/assets/default.scss.css.gz
application.rb has
$ cat config/application.rb require File.expand_path('../boot', __FILE__) # Pick the frameworks you want: require "active_record/railtie" require "action_controller/railtie" require "action_mailer/railtie" require "active_resource/railtie" require "sprockets/railtie" # require "rails/test_unit/railtie" if defined?(Bundler) # If you precompile assets before deploying to production, use this line Bundler.require(*Rails.groups(:assets => %w(development test))) # If you want your assets lazily compiled in production, use this line # Bundler.require(:default, :assets, Rails.env) end module Linker class Application < Rails::Application config.encoding = "utf-8" config.filter_parameters += [:password] config.assets.enabled = true config.assets.initialize_on_precompile = false # For Heroku config.assets.version = '1.0' end end
config/environments/production
has:$ cat config/environments/production.rb Linker::Application.configure do config.consider_all_requests_local = false config.action_controller.perform_caching = true config.assets.precompile += ['default.scss.css','main.css', 'jquery-ui-1.8.22.custom.css'] config.serve_static_assets = false config.assets.compress = true config.assets.compile = false config.assets.digest = true config.log_level = :debug config.i18n.fallbacks = true config.active_support.deprecation = :notify end
This seems to be happening for all assets, e.g.
Started GET "/assets/default.scss-1a27c22229b7b522066181f27af4f07c.css" for 127.0.0.1 at 2014-02-23 10:24:47 -0500 ActionController::RoutingError (No route matches [GET] "/assets/default.scss-1a27c22229b7b522066181f27af4f07c.css"): Started GET "/assets/main-6864687b4114a1c316e444bd90f233ff.css" for 127.0.0.1 at 2014-02-23 10:24:47 -0500 ActionController::RoutingError (No route matches [GET] "/assets/main-6864687b4114a1c316e444bd90f233ff.css"): Started GET "/assets/jquery-ui-1.8.22.custom-24319b4b1218846a3fe22a0479ae98b4.css" for 127.0.0.1 at 2014-02-23 10:24:47 -0500 ActionController::RoutingError (No route matches [GET] "/assets/jquery-ui-1.8.22.custom-24319b4b1218846a3fe22a0479ae98b4.css"): Started GET "/assets/application-fc1d492d730f2a45581a40eac4607db8.js" for 127.0.0.1 at 2014-02-23 10:24:47 -0500 ActionController::RoutingError (No route matches [GET] "/assets/application-fc1d492d730f2a45581a40eac4607db8.js"): Started GET "/images/link.ico" for 127.0.0.1 at 2014-02-23 10:24:48 -0500 ActionController::RoutingError (No route matches [GET] "/images/link.ico"):
-
Raj about 10 yearswhen you precompile, which directory does it write to?
-
Michael Durrant about 10 years+1 Thanks, It seems to be writing to public/assets at least that's where the finger printed files are.
-
Raj about 10 yearsdoes the newly written file name and the filename that is being requested match?
-
Michael Durrant about 10 yearsI added more output from public/assets in the question.
-
Raj about 10 yearsAre you saying file exists and your web server is not rendering it? Problem with your web server. Not Rails. Try visiting that URL manually -
app/assets/application....css
-
Michael Durrant about 10 years
(No route matches [GET] "/assets/default.scss-1a27c22229b7b522066181f27af4f0 7c.css"):
in the log seems to match$ ls public/assets/default*.css public/assets/default.scss-1a27c22229b7b522066181f27af4f07c.css
-
Michael Durrant about 10 yearsok, hmm, that gives me
(No route matches [GET] "/assets/default.scss-1a27c22229b7b522066181f27af4f07c.css"):
-
awendt about 10 yearsBeen bitten by this more than once. Please see my answer.
-
Leo Folsom over 7 yearsWhy should it be false in production? I am using rails_12factor and heroku. Thank you for any further explanation!
-
awendt over 7 years@LeoBrown Rails assumes that in production, you have a web server (Apache, nginx) running before Rails, or even a CDN specifically for static assets. Any of those can serve static assets much faster than Rails.
-
vmarquet about 7 yearsFor Rails 5 : set
config.public_file_server.enabled
totrue
inconfig/environments/production.rb
. -
Victor Ude over 6 years@vmarquet, I just spent way too much time searching for this answer... Devise
<%= link_to('Logout', destroy_user_session_path, method: :delete) %>
in production mode brought me here for those who will inevitably follow. Thanks! -
Glutexo about 6 yearsI would just add, that in Rails 5 the config flag is set by
ENV['RAILS_SERVE_STATIC_FILES'].present?
That means you can run your server withRAILS_SERVE_STATIC_FILES=1 rails server --environment production
and you will be good to go without changing the config file. -
temporary_user_name over 5 years@awendt I'm pretty new to back-end web work (experienced otherwise) and would appreciate any elaboration on your comment here. It sounds like it could be the focus of an entire book. You're saying I would want to have apache and rails running side by side on the same machine to separately serve different parts of the site, the static assets vs the rails-produced html ?