#279 Understanding the Asset Pipeline
Aug 15, 2011 | 11 minutes | Rails 3.1
The asset pipeline is probably the biggest feature in Rails 3.1, but it can seem like magic at first. Here I dive into exactly how the asset pipeline works.
- source codeProject Files in Zip (438 KB)
- mp4Full Size H.264 Video (24.8 MB)
- m4vSmaller H.264 Video (13.5 MB)
- webmFull Size VP8 Video (17.5 MB)
- ogvFull Size Theora Video (28.5 MB)
Nice job as always. Can't wait to see your screencast explaining Tilt in more detail.
Great cast! Could you elaborate on where would you put images and why, in app/assets or public/ directory?
I put images specific for my app in the app/assets/images directory. Depending on the complexity of the application you may want to store some images in the lib/assets or vendor/assets directories. It actually doesn't matter but convention says:
vendor/assets - assets not specific to you app or written by you (Jquery plugins, CSS frameworks, etc)
Nice episode! Would be interesting to see more about Tilt.
This is very useful. Can you please get into more details of the asset pipeline? You have a knack of getting to the point and getting it across.
as always a terrific episode of railscasts.
Do you - or does anyone reading this - know, if coffescript is automatically compiled when application.js is requested? Or do I need to compile it myself and put the resulting .js-file in the assets-folder?
What's best practice for that scenario?
Thank you for you insights.
If the coffeescript gem is in your gemfile, it should compile automatically yes.
You also need a js compiler in your gemfile, rubyracer seems to be a popular choice. At least that was an issue with rc4
Is there a technique for using the assets pipeline on Heroku? Since we can't write to the public directory, I'm wondering if there is a configuration option to use tmp?
Heroku docs for Rails 3.1 explains it:
I'll add to that by saying you have never been able to write to the public folder on heroku anyway. For up-loaders like carrierwave you need to re-define in your model where the tmp upload goes before going off to S3
Heroku precompiles assets for you during push, in the cedar stack. However, it is broken for 3.1 rc6, They are working on fixing it.
About the read only file system:
"Cedar offers an ephemeral writeable filesystem. You can write out to disk anywhere you would like. Your changes will be lost on dyno restart and spin-up."
As always, great railscast. But what'd I'd really like to get peoples' opinion on is how they have/will use this asset pipeline to better merge the work of designers/html coders and web developers (as I'm assuming most of you guys are).
Thanks very much!
scss has a asset-url method you can call.
Rails.application.config.assets.path returns nil for me...
Loading development environment (Rails 3.1.0.rc5)
ruby-1.9.2-p0 > Rails.application.config.assets.path
oops, thx, that works! ;-)
However vendor/assets and lib/assets are not included...
I tried putting something in vendor assets, but it didn't work.
Oh works now, had to restart the server after putting something in vendor. It's probably the same with the lib folder.
Fantastic! This came just as I was scratching my head about a few things. I do have a couple of questions:
2) What happens if I list a file in the manifest that is also included in the require_tree . list? For example, I have a JS file that I need to ensure it loads before anything else. I list it manually, right above the require_tree line; will that file then be included twice?
1) You have to reference those files appropriately as
subfolder/someFile.js. There is no collision.
2) Every file is only included once - the first time it is required implicitly or explicitly.
But, which file is included first? Which file is implicitly referenceable by "someFile.js" vs explicitly? Alphabetically by directory?
Any tricks for speeding up asset serving in development?
When I have been playing with a 3.1 branch of our main rails app at work I experience terribly slow performance. I gather this is because Rails is serving every request for every asset (as seen in the log) instead of Unicorn doing it.
I ask since the performance I see is so bad I can't imagine any developer coping with it... hence I must be missing some crucial bit of information.
I guess the reason assets don't work like Compass (which generates static files in public) is that I can make use of a full request object with session and all in my assets or something?
For me in the development it is not that slow.
Although during JS unit testing it is. But it is solved by guard-rails-assets.
Use the rails-dev-tweaks gem and you have your speed back. ;-)
This gem seems pretty dead now.
I've got the same problem (unicorn taking long time to compile assets in dev) and am using the rails-dev-tweaks gem, which still doesn't speed the compilation up...
Any other ideas?
However, you didn't show how you would go about including the /admin js files when viewing an admin view. How would you do that?
+1 I just jumped into the comments to mention this issue also :) Glad someone else has already noticed.
Assets Pipeline has nothing to do with including the scripts.
you can use
config.assets.precompileto configure which assets will be generated. But that's about it.
If you want to include the script into
/adminpages just use normal
Don't know where in the rails stack this logic is executed, but if there is access to instance variables per request then you could:
Add .erb onto the end of your application.js file => application.js.erb
Do something like:
I guess what you mean is: "how do I include /admin.js alongside my general CSS stylesheet in the admin view in a single file ?"
Your JS files aren't supposed to be regenerated every request, and won't in production - so I would discourage using Donnie's solution.
The only solution is to include your 'screen' stylesheet in your admin stylesheet and include only the 'admin' stylesheet in your layout like Dmytrii suggested.
Ryan shows how to avoid a CSS collision in Episode #264 @ about 10:17 when discussing how the ActiveAdmin CSS can cause a conflict with the normal CSS.
Removing from the application.css file:
*= require_tree .
and manually loading each of them in works much better.
WOOT! I am very very glad to see my Railscast request was featured! +1 So very useful thanks Ryan!
Also I may have missed it but how does one handle naming conflicts? I'll re-watch...
When there are naming conflicts, the first path that appears in the
config.assets.pathsarray is the file that is chosen. This can be avoided by using the
asset_path()helper and specifying the directory.
Great screencast! You should probably link to the current asset pipeline docs on github. There have been a lot of changes to the docs since Ryan posted that page!
Yes, awesome rails cast as usual!
I did a few blog posts on asset related rails awhile back, might be of interest?
Asset pipeline is awesome, but how to deal with scripts like lightbox or wysiwyg, that distributed in one folder with local paths for included js, css and images? How to deal with this via asset pipeline?
By the by, how can I do this?
I have my assets folder structure like this
I want the project.js and projectValidate.js to be added in my application.js as a part of asset pipe-lining only when actions in product controller is called and store.js when actions in store controller is called.
Thanks for the bundler open tip. I have always wondered a quick way to open up my gems.
Hope this helps others.
It've been confused as well, that the sprocket directive
and create a file /vendor/assets/stylesheets/application.css containing:
This is not an error from the doc. Indeed, "require_tree ." means that the manifest requires the file dans the subfiles (the "tree") in the current directory (the "." means current directory).
And the lib and vendor directories aren't subdirectories of the current directory.
So your way to do it is good ;)
if you want controller specific scripts or stylesheets, you can do something like this:
Just a quick note for anyone using mongomapper or mongoid, or anything that requires removing active record but removing the line
make sure you add:
this is not currently documented
note that if you precompile your assets in dev, you'll need to mv or rm /public/assets if you want any future changes to a .css.sass file to show up. At least that is the case here :)
why can't i access http://127.0.0.1:3000/assets/applications.js
its show me
No route matches [GET] "/assets/applications.js"
I'm fairly new to rails. Would someone explain why jquery plugins work normally on localhost but fail to do so when deployed to heroku
I`m clone repo
but js and css file does`t load.
If I look at the source code of a site:
link href="/assets/application-7270767b2a9e9fff880aa5de378ca791.css" media="screen" rel="stylesheet" type="text/css" /
Why don`t load other js/css file?
In 1 mim resolved all of my problem tks..
came back please srsrsr
Can we put code in products.js.coffee / home.js.coffee to application.js? so there will be less file in the folder and those files won't be necessary?
Threre's a typo for a link in the ASCIIcast. In http://railscasts.com/episodes/279-understanding-the-asset-pipeline?view=asciicast in the first paragraph, "http://ryanbigg.com/guides/asset_pipeline.html" should be "http://guides.rubyonrails.org/asset_pipeline.html"
But that doesn't diminish the goodness of the episode -- thanks!
This cast is awesome, even years later as it truly helps out!
As an add-on question to developing with this, I'd like to know the following as I'm struggling with it. If you're ADDING to an existing library (ie., extending a bootstrap CSS file), then it look like the sprockets library is ALWAYS needed at the top of your SCSS files. Attempted to add in the sprockets by default in the application.css file, but it looks like the pre-parsers error - as it cannot locate the $gray-medium-light: variable in bootstrap when running. Only when the IMPORT lines are pre-pended in the file does it actually run. Is this really needed in each/every one of my CSS files which overload/extend bootstrap?
Example (in application.css) -- which I thought would globally load the bootstrap.css
Example of my file after having to add the @import to my css file
<--- MYFILE.CSS.SCSS --->
/* universal */
Any ideas on how to get bootstrap to load globally so I can extend it in my CSS files?