2. Table of Contents
01 The pain of assets in 3.0
02 Asset Pipeline to the rescue
03 New Stuff
04 Deployment story
Asset Pipeline !"#$%&'(&)*+%,
3. Bad Organization
stylesheets
ROOT/public javascripts
images
Asset Pipeline !"#$%&'(&)*+%,
One of the big pains in how Rails pre 3.1 handles assets is organizational. You have one
place to put all your assets, one place to put stylesheets, one place to put javascripts, and
one place to put images. But what ends up happening?
4. application code
third party code
Asset Pipeline !"#$%&'(&)*+%,
Big Ass Folders
Mixing 3rd party code
How do you update?
Mixing abstractions
be like extracting rails into your project
5. lowercase d dependencies
‣ application.html.erb
<%= stylesheet_link_tag 'default',
'index' %>
<%= javascript_include_tag 'jquery',
'rails', 'application' %>
Asset Pipeline !"#$%&'(&)*+%,
ad hoc dependency declaration
6. Table of Contents
01 The pain of assets in 3.0
02 Asset Pipeline to the rescue
03 New Stuff
04 Deployment story
Asset Pipeline !"#$%&'(&)*+%,
7. Assets as First Class Citizens
‣ Better Opinions
‣ Empty Files and Folders
‣ Generators
‣ Capital-D Dependencies
Asset Pipeline !"#$%&'(&)*+%,
8. Better Opinions
app/assets stylesheets
lib/assets javascripts
vendor/assets images
Asset Pipeline !"#$%&'(&)*+%,
Now assets are in 3 places.
app/assets holds the code you write for this specific application
lib/assets holds the generic library code you write for this application
vendor/assets holds third party code
9. app/assets
localhost:3000/assets/application.js
Asset Pipeline !"#$%&'(&)*+%,
Now, when you generate a new rails 3.1 app, you get two assets, application.js and
application.css in app/assets.
And now that 3.1 ships with jQuery by default, where is that?
11. vendor/assets
localhost:3000/assets/ie6_screen.css
Asset Pipeline !"#$%&'(&)*+%,
3rd party
12. Capital-D Dependencies
‣ app/assets/javascripts/application.js
//= require jquery
//= require jquery_ujs
sprockets
Asset Pipeline !"#$%&'(&)*+%,
looks like ruby require
require inlines the code when application.js is served, in order.
But where are these files?
13. Capital-D Dependencies
‣ Gemfile
gem 'jquery-rails'
https://github.com/rails/jquery-rails
//= require jquery
//= require jquery_ujs
Asset Pipeline !"#$%&'(&)*+%,
So we’ve declared our dependency on jquery and jquery_ujs in our application.js file, but
where are these files?
Well, now gems can have their own assets, and rails 3.1 ships with this jquery-rails gem in
your Gemfile, which provides jquery and jquery_ujs files necessary to work with the
framework.
Notice the familiar layout for assets, vendor/assets/javascripts.
14. Don’t like jQuery?
‣ Gemfile
# gem 'jquery-rails'
gem 'prototype'
‣ app/assets/javascripts/application.js
//= require prototype
Asset Pipeline !"#$%&'(&)*+%,
Now its also very easy to switch back to prototype, or some other javascript library.
15. Including assets
‣ application.html.erb
<%= stylesheet_link_tag 'application' %>
<%= javascript_include_tag 'application' %>
(function( window, undefined ) {
// all of jquery here
})( jQuery );
(function() {
// application code here
}).call(this);
Asset Pipeline !"#$%&'(&)*+%,
In your application.html.erb, you would define which stylesheets and javascripts you would
need.
16. Generators
‣ rails generate assets Post
‣ rails generate scaffold User
Asset Pipeline !"#$%&'(&)*+%,
Another way rails 3.1 makes assets into a first class citizen is through generators.
So now that we have a place to put resource specific asset code, how do we include these in
our app?
17. Dependency Directives
‣ app/assets/javascripts/application.js
//= require jquery
//= require jquery_ujs
//= require_tree .
require app/assets/javascripts/**/*
Asset Pipeline !"#$%&'(&)*+%,
require_tree will require all files in javascripts, and any nested folders.
18. More Directives
‣ require
‣ require_tree .
‣ require_self
‣ require_directory ‘posts’
‣ include ‘file’
‣ depend_on ‘file.png’
Asset Pipeline !"#$%&'(&)*+%,
require_self takes the code from the current file and inlines it in place, helps when requiring
dependencies after require_self that depend on the current file
require_directory is similar to require_tree, but it wont traverse nested directories
include works like require, but will always insert the content even if its been required already
depend_on will declare a dependency that doesn’t get required, but is used for caching
purposes * will go into caching stuff more later
19. Table of Contents
01 The pain of assets in 3.0
02 Asset Pipeline to the rescue
03 New Stuff
04 Deployment story
Asset Pipeline !"#$%&'(&)*+%,
20. CoffeeScript and Sass
‣ Gemfile
group :assets do
gem 'sass-rails'
gem 'coffee-script'
end
Default in 3.1
Asset Pipeline !"#$%&'(&)*+%,
The asset group is required by default in development and test environments, but not in
production.
21. CoffeeScript and Sass
‣ app/assets/javascripts/application.js.coffee
jQuery ($) ->
$('.truncate-more-link').live 'click', (e) ->
$this = $ this
# do more stuff here
‣ app/assets/stylesheets/application.css.scss
$blue: #3bbfce;
$margin: 16px;
.content-navigation {
border-color: $blue;
color: darken($blue, 9%);
}
Asset Pipeline !"#$%&'(&)*+%,
Before they are served to the browser, the asset pipeline passes these files through their
respective preprocessors.
22. Generators
‣ rails generate assets Review
‣ rails generate scaffold Comment
Asset Pipeline !"#$%&'(&)*+%,
Now generators work with coffeescript and sass and generate the appropriate files
23. Chaining Preprocessors
‣ app/assets/stylesheets/application.css.scss.erb
$blue: #3bbfce
$margin: 16px
.content-navigation
background: url(<%= asset_path(‘background.png’) %>)
color: darken($blue, 9%)
$blue: #3bbfce
$margin: 16px
.content-navigation
background: url(/assets/background-374e12d5b46ffa3d2f92a11dbae9b06a.png)
color: darken($blue, 9%)
Asset Pipeline !"#$%&'(&)*+%,
Before they are served to the browser, the asset pipeline passes these files through their
respective preprocessors.
25. Table of Contents
01 The pain of assets in 3.0
02 Asset Pipeline to the rescue
03 New Stuff
04 Deployment story
Asset Pipeline !"#$%&'(&)*+%,
26. rake assets:precompile
‣ app/assets/stylesheets/application.css.scss.erb
$blue: #3bbfce
.content-navigation
background: url(<%= asset_path(‘background.png’) %>)
color: darken($blue, 9%)
‣ public/assets/application-e317be572968fcf8892b5c767f776d82.css
.content-navigation {
background: url(/assets/background-92a96fe5e422523a2de56c9f0defe51b.png);
color: #2ca2af;
}
Asset Pipeline !"#$%&'(&)*+%,
All assets get compiled into public/assets, where they can easily be served by your webserver
or a CDN.
27. Precompile
‣ config/deploy.rb
before :"deploy:symlink", :"deploy:assets";
desc "Compile assets"
task :assets do
run "cd #{release_path}; RAILS_ENV=#{rails_env} bundle exec
rake assets:precompile"
end
Asset Pipeline !"#$%&'(&)*+%,
28. Caching
<script src="/javascripts/application.js?1292365692">
</script>
<script src="/assets/
application-374e12d5b46ffa3d2f92a11dbae9b06a.js">
</script>
depend_on
Asset Pipeline !"#$%&'(&)*+%,
Rails used to append a deploy timestamp to all asset paths to reset the cache.
With the asset pipeline, there is no deploy timestamp. Instead, rails will include an MD5 hash
of the contents of the file in the filename itself.
So now the cache stays fresh until the file actually changes, so if you are deploying a lot, but
not changing the asset files, then you should see some nice performance improvements.
29. Compression
‣ config/environments/production.rb
# Compress both stylesheets and JavaScripts
config.assets.compress = true
gem 'uglifier' requires js runtime
Asset Pipeline !"#$%&'(&)*+%,
Both Mac OS X and Windows ship with javascript runtimes
If you are deploying to heroku you can use therubyracer-heroku, which includes a build of
nodejs specifically for heroku, but it will bloat your heroku slug size by 30MB
30. Rails 3.1 Asset Pipeline
Any questions?
Asset Pipeline !"#$%&'(&)*+%,