Skip to content

Instantly share code, notes, and snippets.

@jnewman12
Last active January 10, 2017 08:12
Show Gist options
  • Select an option

  • Save jnewman12/d64dab2c0368c4a2ea81fbb1b56737ae to your computer and use it in GitHub Desktop.

Select an option

Save jnewman12/d64dab2c0368c4a2ea81fbb1b56737ae to your computer and use it in GitHub Desktop.
Asset pipeline lesson

Rails Asset Pipeline

asset pipeline


Objectives

  • 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

What is the Asset Pipeline?

  • 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

Sprockets

  • The asset pipeline is implemented by the sprockets-rails gem, 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-sprockets option.
    • 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'

Main Features of the Asset Pipeline

  • 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 .js file and all CSS files into one master .css file
  • 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.

What is finger printing?

  • 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.

How to use the Asset Pipeline?

  • There are two basic ways that the asset pipeline is used:
  1. When running a server in development mode, it automatically pre-processes and prepares your assets on-the-fly.
  2. 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


File Structure

  • 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:

asset pipeline file structure


Asset Paths

  • 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 stylesheets
    • lib/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 applications
    • vendor/assets: is for assets that are owned by outside entities, such as code for JavaScript plugins and CSS frameworks

The manifest

  • 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

Manifest Search Paths

  • 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/assets folder, but these subdirectories are not special - any path under assets/* 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.js is referenced as //= require sub/something

  • You can view the search path by inspecting Rails.application.config.assets.paths in the Rails console


Asset Path Usage

  • 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:

asset pipeline usage


Adding Links to Assets

  • 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" %>

CSS and ERB

  • 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.

Javascript and ERB

  • 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).

Asset Pipeline in Development

  • 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


Asset Pipeline in Production

  • 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" />

Precompiling Assets

  • 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

Conclusion

  • 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.

rails asset pipeline docs


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment