Configuration: Rails 4, HTML, CSS, on Heroku.
I have a Rails 4 app that has been in production for five months. Here's what's in my production.rb:
config.serve_static_assets = false
# Do not fallback to assets pipeline if a precompiled asset is missed.
config.assets.compile = false
# Generate digests for assets URLs.
config.assets.digest = true
config.assets.enabled = true
config.assets.initialize_on_precompile = true
config.action_controller.asset_host = "//dynasfakeurl.cloudfront.net"
Whenever I push to production, I clean my assets using rake assets:clean, then precompile them using rake assets:precompile. This fingerprints my assets, and pushes it directly to my S3 static file bucket, which are served via cloudfront. I then push my app live to Heroku.
On the .html.erb homepage, I call my static files via Rails tags like this:
<%= image_tag "picture.png" %>
<%= stylesheet_link_tag "application" %>
Which render correctly using fingerprints. For example, the second one most recently generated this asset path: http://dynasfakeurl.cloudfront.net/assets/application-17892abdffc77f1fb1be125bab.css
Usually, this works great. However, I've had a problem, twice now, where after 12-16 hours of my last push, all of my asset paths spontaneously lose their fingerprints. For example, the stylesheet tag last generated this asset path: http://dynasfakeurl.cloudfront.net/stylesheets/application.css. Which doesn't exist. Thus, when I load the page, it fails to load the assets.
I've been stuck for the past few hours trying to debug this, but can't figure out why my asset paths would spontaneously, without me pushing anything, lose their fingerprints in production.
Related
I try to update an old rails application.
It was original written with rails 2.3 and works now with rails 5.0.7
It does not use the asset pipeline, as there is not much css and js, and think it would make updating even more complex.
When trying to update to Rails 5.1, it seem now to wanting to use the asset pipeline, and throws errors:
<%= stylesheet_link_tag 'stylesheetfile.css' %>
ActionView::Template::Error (The asset "stylesheetfile.css" is not present in the asset pipeline.
):
I have already tried the following in application.rb
config.assets.enabled = false
When in production mode, rails can't seem to find any precompiled assets from the asset pipeline.
I'm using rails 3.2.0 and ruby 1.9.3 running inside RVM on CentOS. No additional web server is running in conjunction with this application. The application was only recently updated to use the asset pipeline, as it was originally a rails 3.0 app.
After running
rake assets:clean
rake assets:precompile
I see the hashed content in public/assets, as I would expect. The hashes at the end of the files match those I see in the page source.
Yet at runtime, here's what I see for every asset Rails tries to serve:
Started GET "/assets/application-892c6227e631daf9a8e041b1d4d002ec.css" for 75.149.58.169 at 2012-03-14 11:42:43 -0700
ActionController::RoutingError (No route matches [GET] "/assets/application-892c6227e631daf9a8e041b1d4d002ec.css"):
I'm not referring to the folder that each asset is housed in; all references to assets look like these:
//css:
.class {
background: url(asset.png) no-repeat;
}
//erb:
<%= image_tag "asset.png" %>
<%= link_to "page", :class => "class" %>
Asset pipeline pertinent settings in production.rb:
config.serve_static_assets = false
config.assets.enabled = true
config.assets.compress = true
config.assets.debug = false
config.assets.compile = false
config.assets.digest = true
And lastly, asset settings from config/application.rb:
config.assets.enabled = true
config.assets.version = '1.0'
The user starting the rails server process has read, write and execute permissions on public/assets, so I don't think it's a permissions issue. Have I missed a configuration step?
Edit
I noticed that there are no errors stating that assets are not precompiled, so I tried to access a stylesheet from the web page by appending"/assets/application-892c6227e631daf9a8e041b1d4d002ec.css" to the end of the host path:
http://www.myapp.com"/assets/application-892c6227e631daf9a8e041b1d4d002ec.css"
This worked and the stylesheet opened.
Further researching of this issue yielded this SO article:
application.css not being served as an asset
It seems
config.serve_static_assets = false
Is an incorrect setting as long as my Rails application is not running behind Apache or nginx
I had this same problem, but I note that your stylesheet is pointing to the non-fingerprinted, non-cached version of the files. If you are using the asset pipeline, in order to take advantage of it, you need to use the helpers that point to the fingerprinted, cached version of the files. To do this, you'll need to either embed erb in your css file, or use sass.
Incorrect:
.class {
background: url(asset.png) no-repeat;
}
Correct (uses sass):
.class
background: image-url('asset.png') no-repeat
For more info, see here: http://guides.rubyonrails.org/asset_pipeline.html#coding-links-to-assets
If you don't care about the performance issues, you can get away with using the non-cached versions until you upgrade to Rails 4 or Rails 3.2.16, because those versions introduce breaking changes that force you to use the asset pipeline (and its corresponding syntax). If you don't use the new syntax, the non-cached versions will not work at all on production.
I know there are a million questions already on this, but I can't get this.
I want to include most of my JS files in the asset pipeline, but I have a few I want to load conditionally (or only on certain pages). These are big, complicated files and will never, ever be used by 95% of the users, so I'd rather not have them loaded for every user. One set of JS files is for a calendar, placed in:
app/assets/javascripts/calendar
So my manifest is set up to include only the top directory (and exclude the calendar subdirectory):
//= require jquery
//= require jquery_ujs
//= require jquery-ui
//= require_directory .
My config/environments/production.rb:
# Compress JavaScripts and CSS
config.assets.compress = true
# Don't fallback to assets pipeline if a precompiled asset is missed
config.assets.compile = false
# Generate digests for assets URLs.
config.assets.digest = true
# This following config is left over from previous Rails app,
# so not sure if it's now unnecessary ...
# Disable Rails's static asset server
# In production, Apache or nginx will already do this
config.serve_static_assets = false
In the view, I'm using Ryan Bates' nifty_layout to manually include the calendar files:
javascript "calendar/date.js", "calendar/jquery.weekcalendar.js", "calendar/custom.js"
I've tried precompiling in both development and production -- the docs aren't clear where I'm supposed to do this, but it looks like production.
And when I run the page, I get this:
ActionView::Template::Error (calendar/date.js isn't precompiled)
I don't want it precompiled. I want it loaded manually. (Actually, it would be OK to precompile in a file other than the main application.js that is created, but I don't know how to do that.)
What's the solution?
Thanks!
OK, I didn't realize this was how it works, but I think I figured it out.
Add the files to be manually loaded to config/environments/production.rb like so:
config.assets.precompile += %w( calendar/*.js jquery_calendar/*.css )
I thought this just folded them into the application.js and application.css, but apparently not -- it compiles them as individual files.
Then, you can call the files as you traditionally would (in this case, using nifty_layout):
javascript "calendar/date.js", "calendar/jquery.weekcalendar.js", "calendar/custom.js"
My application is deployed on Rails 3.1 and on Heroku.
1. In production.rb, if I have config.assets.compile = true only then active_admin works. However, in production, I want config.assets.compile = false for normal application CSS and JS. The active admin module will be used only by administrator so it can be slow.
2. Moreover, since I installed active_admin gem my normal CSS has got terribly disturbed.
Hence, I want to somehow split the CSS and JS of active_admin and normal application so that:
1. Only when I hit localhost:3000/admin then CSS and JS of active admin hits and that of normal app does not. When I am on any other URL, then CSS and JS of normal app hits but active admin's does not.
2. I can config.assets.compile = false to normal app CSS and JS while make it config.assets.compile = true for active_admin alone.
Is this possible?
The good news is that you can have .compile set to false for both, and have both run fast!
Active admin uses its own manifests that start with 'active_admin'. By default these won't be precompiled by Rails.
To get them precompiled you need to add these files to the precompile array in production.rb:
config.assets.precompile += ['active_admin.js', 'active_admin.css']
This will create the files in the /assets folder and allow you to set .compile to false all the time.
Don't forget to also set:
config.assets.digest = true
I have my Rails 3.1.0 application running with passenger in production environment and I have a section where the application allows the user to change his profile picture so I upload the image using an ajax uploader and in my controller I upload the file and generate different sizes for the image with rmagick then I render the new image with an image_tag but the application won't show the image till I restart the server.
What I get is No route matches [GET] "assets/path/to/image.png"
If I restart the server It will show the image, but obviously I can't be restarting the server every once a user uploads a new image.
How can I solve the keeping the assets working the right way?
The Rails asset pipeline is really meant for structural / design images, such as backgrounds, icons, banners, etc..). Dynamic assets should go in the public directory [source below]
It's probably a good idea to serve static assets through Nginx or Apache or whatever your web-server is, or place them in the public directory of your Rails app.
That should solve your problem right there.. e.g. make a separate path for static assets into which you upload those images with rmagick / carrierwave, or whatever gem you prefer.
The asset pipeline only knows about images which are present during start-up. So separating static / uploaded assets into a separate directory , and serving it directly through the web-server, will help -- it should also be much faster.
you'll need something like this in your configuration:
# Disable Rails's static asset server (Apache or nginx will already do this)
config.serve_static_assets = false
# Compress JavaScripts and CSS
config.assets.compress = true
# Don't fallback to assets pipeline if a precompiled asset is missed
config.assets.compile = false
# Generate digests for assets URLs
config.assets.digest = true
# UNCOMMENT the header that your server uses for sending files
# config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
# config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
More General:
http://railscasts.com/episodes/279-understanding-the-asset-pipeline
http://guides.rubyonrails.org/asset_pipeline.html
Rails 3.1: Should File Uploads be added to asset pipeline?
Regarding serving images outside asset pipeline:
http://mrjaba.posterous.com/rails-31-asset-pipeline-with-nginx-and-passen
http://trackingrails.com/posts/rails-31-and-asset-pipeline-problems-with-apache
http://pastebin.com/kC4Ba40U
https://github.com/defunkt/resque/issues/418