Rails App Not Serving Assets in Production Environment
可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
My app works fine when run in development environment. In production (rails server -e production), the browser can't access the css and js files and on the console there are messages like:
I, [2013-07-27T21:00:59.105459 #11449] INFO -- : Started GET "/javascripts/application.js" for 99.102.22.124 at 2013-07-27 21:00:59 +0000 F, [2013-07-27T21:00:59.108302 #11449] FATAL -- : ActionController::RoutingError (No route matches [GET] "/javascripts/application.js"):
The head section from html source when in production environment:
a Social Server
In development env on the other hand the head section looks like:
a Social Server
The app does not use a database, so I have disabled ActiveRecord. Snippets of the config files:
source 'https://rubygems.org' gem 'rails', '4.0.0' gem 'sass-rails', '~> 4.0.0' gem 'uglifier', '>= 1.3.0' gem 'coffee-rails', '~> 4.0.0' gem 'jquery-rails' gem 'jquery-ui-rails' gem 'turbolinks' gem 'jbuilder', '~> 1.2' group :doc do gem 'sdoc', require: false end group :twitter do gem 'twitter', '4.8.1' end group :instagram do gem 'instagram', '0.10.0' end group :tumblr do gem 'tumblr_client' end gem 'twitter-bootstrap-rails' gem 'therubyracer' #needed for runtime js on amazon ec2.
I apologize for posting so much info. I felt the info might be relevant.
p.s. I have only half baked knowledge of rails, so bear with me. Thanks~
回答1:
When testing locally your production environment, you have to compile the assets locally. Simply run the command below:
It will generate all the assets under public/assets.
Next, you have to tell Rails to serve the assets itself. Server software (eg. Nginx or Apache) do it for you on environments like Heroku, but locally you should let Rails do it. Change this in your production.rb:
config.serve_static_assets = true
But make sure you set it back to false before pushing your code to production!
I found a blog that suggests this is a bug in the Rails 4.0.0 asset pipeline, and is inexplicably mitigated by setting...
config.assets.compile = true
... in config/environments/production.rb
Aside from somehow kicking the asset pipeline in to actually working, that setting will turn on live-compilation of assets. That is normally a bad thing for performance in production, but if you still manually precompile assets when you deploy, with
rake assets:precompile
... the live-compilation should never happen (because the necessary assets have already been precompiled).
I hope this helps :)
回答3:
As previously noted config.serve_static_assets is deprecated and replaced by config.serve_static_files. If one examines config/environments/production.rb for Rails-4.2 then one finds this:
# 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?
The implication being that setting and exporting (in BASH) the environment variable export RAILS_SERVE_STATIC_FILES="to any value whatsoever" in a session prior to running rails s -e production will give the desired result when testing locally and also will avoid having to remember to recode production.rb before pushing to the production host.
If you are pushing precompiled assets to a production server there is a chance that you are preventing hidden 'dot' files being pushed and this essential file won't make it into production.
In my environment I need to precompile assets in an integration environment and push these to production so that there is no need to compile the assets on the production machine. I was erroneously blocking all hidden files from being pushed to production machine.
To see if this answer works for you, check your generated HTML source in a browser from the production server to see if the assets path has been generated. If you see your script tag like this:
check the src attribute. It should start with /assets/javascript. In this case it starts with /javascript which indicates Rails does not think any of the assets have been precompiled.
I corrected this by updating my push to production (currently rsync), ensuring I push the .sprockets-manifest* file after precompiling on my integration server.
Also, I use standalone Passenger as my integration test server, rather than Webrick, since it handles more realistic serving of static files.
回答6:
I think to Rails 4.x you have to precompile assets to production or use config.assets.compile even both if needed.
The default Rails behavior for production environment is to "Do not fallback to assets pipeline if a precompiled asset is missed." So, don't. Use to not compi
config.assets.compile = false
If you use this option you don't need to use:
config.serve_static_files = true
Because if the asset wasn't precompiled, Rails will compile before serve request.
But if you do precompile the assets before production you don't needs config.assets.compile = true, but you need config.serve_static_files = true to Rails serve requests if you don't have http_server to serve the precompiled assets.
The setting config.serve_static_assets is deprecated.
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.
I hope this answer help you(reader) to understand whats really happens
回答7:
The following command works for me locally.
rails server -e production
I got the same error "ActionController::RoutingError (No route matches [GET] "/assets/application.css"" while running "rails s". Even after I precompiled the source, change config precompile true. It still could not load properly.
The option "-e production" made those RoutingError disappear.