- Understand the asset pipeline, and the benefits we get for using it
- Learn about Sprockets, and what it does for us behind the scenes
- Understand asset paths and helpers
- The asset pipeline provides a framework to concatenate and minify or compress JavaScript and CSS assets.
- It also adds the ability to write these assets in other languages and pre-processors such as CoffeeScript, Sass and ERB.
- It allows assets in your application to be automatically combined with assets from other gems.
- For example, jquery-rails includes a copy of jquery.js and enables AJAX features in Rails
- The asset pipeline is implemented by the
sprockets-railsgem, and is enabled by default. - Sprockets performs the asset packaging which takes the assets from all the specified paths, compiles them together and places them in the target path (public/assets)
- Sprockets is a gem that allows us to add rake tasks to handle our static assets like css and js
- You can disable it while creating a new application by passing the
--skip-sprocketsoption.rails new appname --skip-sprockets
- Rails automatically adds the sass-rails, coffee-rails and uglifier gems to your Gemfile, which are used by Sprockets for asset compression
gem 'sass-rails'gem 'uglifier'gem 'coffee-rails'
- The first feature of the pipeline is to concatenate assets, which can reduce the number of requests that a browser makes to render a web page.
- Web browsers are limited in the number of requests that they can make in parallel, so fewer requests can mean faster loading for your application.
- Sprockets concatenates all JavaScript files into one master
.jsfile and all CSS files into one master.cssfile - The second feature of the asset pipeline is asset minification or compression.
- For CSS files, this is done by removing whitespace and comments. For JavaScript, more complex processes can be applied. You can choose from a set of built in options or specify your own.
- The third feature of the asset pipeline is it allows coding assets via a higher-level language, with precompilation down to the actual assets.
- The higher level supported languages include Sass for CSS, CoffeeScript for JavaScript, and ERB for both by default.
- In production, Rails inserts an MD5 fingerprint into each filename so that the file is cached by the web browser.
- Fingerprinting is a technique that makes the name of a file dependent on the contents of the file.
- When the file contents change, the filename is also changed. For content that is static or infrequently changed, this provides an easy way to tell whether two versions of a file are identical, even across different servers or deployment dates.
- These file are almost like of migration files
- When a filename is unique and based on its content, HTTP headers can be set to encourage caches everywhere (whether at CDNs, at ISPs, in networking equipment, or in web browsers) to keep their own copy of the content.
- When the content is updated, the fingerprint will change. This will cause the remote clients to request a new copy of the content. This is generally known as cache busting.
- There are two basic ways that the asset pipeline is used:
- When running a server in development mode, it automatically pre-processes and prepares your assets on-the-fly.
- In production mode, you’ll probably use it to pre-process, versionize, and compress and compile your assets. You can do so by running the following command:
-
bundle exec rake assets:precompile -
we will see this command when we start deploying on heroku
-
This will create (by default) an assets directory in your public/ folder. It will then add all the compressed and compiled files into that directory, in the appropriate formats and with the new digested versions.
-
You can then set up Nginx or Apache to serve those files directly so that Rails doesn’t have to deliver them (and run the on-the-fly preprocessing, etc.) itself.
-
Remember that defaults can be changed, so if things aren’t working as expected, check your application configuration file in config/application.rb.
-
In Rails 4, asset handling is typically configured in config/initializers/assets.rb
- It’s important to organize your assets in a way that is understandable to you, and facilitates the existing functionality of the asset pipeline.
- The first thing you should know is that all of your custom Javascript, stylesheets, and images should go in the
app/assets/directory. - By default, there is a folder each for javascripts, stylesheets, and images. You can also add fonts, audios, and videos to the
app/assets/directory for those types of assets. - All third-party code that you are using (e.g. jQuery, backbone.js, etc.) should be placed in the vendor/assets/ directory:
- Rails applications default to having three possible asset paths:
app/assets: is for assets that are owned by the application, such as custom images, JavaScript files or stylesheetslib/assets: is for your own libraries’ code that doesn’t really fit into the scope of the application or those libraries which are shared across applicationsvendor/assets: is for assets that are owned by outside entities, such as code for JavaScript plugins and CSS frameworks
- The keystone of the asset pipeline is the manifest file.
- By default, Rails creates one for stylesheets (app/assets/stylesheets/application.css) and JavaScript files (app/assets/javascripts/application.js).
- This file uses directives to declare dependencies in asset source files
-
When a file is referenced from a manifest or a helper, Sprockets searches the three default asset locations for it.
-
The default locations are: the images, javascripts and stylesheets directories under the
app/assetsfolder, but these subdirectories are not special - any path underassets/*will be searched. -
For example, if you had a list of files like this
app/assets/javascripts/home.js lib/assets/javascripts/moovinator.js vendor/assets/javascripts/slider.js vendor/assets/somepackage/phonebox.js -
It would be referenced in the manifest like this
//= require home //= require moovinator //= require slider //= require phonebox -
Assets inside sub-directories can also be searched and referenced
-
For example,
app/assets/javascripts/sub/something.jsis referenced as//= require sub/something -
You can view the search path by inspecting
Rails.application.config.assets.pathsin the Rails console
- Using the asset pipeline is very simple. All it involves is placing assets (js/css/images/other) into the asset path.
- You can access the files using multiple helper methods within your views:
- Sprockets does not add any new methods to access your assets - you still use the familiar javascript_include_tag and stylesheet_link_tag:
<%= stylesheet_link_tag "application", media: "all" %>
<%= javascript_include_tag "application" %>- If using the turbolinks gem, which is included by default in Rails, then include the 'data-turbolinks-track' option which causes turbolinks to check if an asset has been updated and if so loads it into the page:
<%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => "true" %>
<%= javascript_include_tag "application", "data-turbolinks-track" => "true" %>- In regular views you can access images in the public/assets/images directory like this:
<%= image_tag "rails.png" %>
- The asset pipeline automatically evaluates ERB. This means if you add an erb extension to a CSS asset (for example, application.css.erb), then helpers like asset_path are available in your CSS rules:
.class { background-image: url(<%= asset_path 'image.png' %>) }- This writes the path to the particular asset being referenced. In this example, it would make sense to have an image in one of the asset load paths, such as app/assets/images/image.png, which would be referenced here.
- If you add an erb extension to a JavaScript asset, making it something such as application.js.erb, you can then use the asset_path helper in your JavaScript code:
$('#logo').attr({ src: "<%= asset_path('logo.png') %>" });
- When writing JS (and css), we can use our snowcones inside our css and js files because these files go through the asset pipeline. Inside the asset pipeline, the snowcones are evaluated, which leaves us with a convient way to write rails code inside of javascript (or css).
- In development mode, assets are served as separate files in the order they are specified in the manifest file.
- a manifest like this app/assets/javascripts/application.js:
//= require core //= require projects //= require tickets
would turn into this
<script src="/assets/core.js?body=1"></script>
<script src="/assets/projects.js?body=1"></script>
<script src="/assets/tickets.js?body=1"></script>The body param here is required by Sprockets
-
In the production environment Sprockets uses the fingerprinting scheme outlined above. By default Rails assumes assets have been precompiled and will be served as static assets by your web server.
-
During the precompilation phase an MD5 is generated from the contents of the compiled files, and inserted into the filenames as they are written to disk. These fingerprinted names are used by the Rails helpers in place of the manifest name.
<%= javascript_include_tag "application" %>
<%= stylesheet_link_tag "application" %>generates something like this
<script src="/assets/application-908e25f4bf641868d8683022a5b62f54.js"></script>
<link href="/assets/application-4dd5b109ee3439da54f5bdfd78a80473.css" media="screen" rel="stylesheet" />-
When we deploy to production environments, we will need to bundle our assets together and precompile all of our single files into 1 very large file
-
You can call this task on the server during deployment to create compiled versions of your assets directly on the server.
RAILS_ENV=production bundle exec rake assets:precompile
- This minifies and compresses all of your assets (images [into smaller files for efficiency], css, and js) in an effort to reduce page load time
- The asset pipeline has three goals: precompile, concatenate and minify assets.
- Precompilation let’s you use higher-level languages to create actual assets (for example, Sass to CSS, Coffeescript to JS).
- Concatenation is very important in the production environment. It can reduce the number of requests that a browser makes to render a web page, which leads to faster load time.
- Minification takes out the extra whitespace and comments from your assets. This allows for smaller asset file size, which leads to faster load times.

