Should you use the Asset Pipeline?

In this blog post I will be comparing the asset pipeline to some JavaScript alternatives. I’ll explain what the asset pipeline does and then I’ll talk about the alternatives. Lastly, I’ll share my thoughts on which one you should use.

What is the Asset Pipeline?

The asset pipeline is part of Rails, it’s job is to concatenate and compress JavaScript and CSS assets. It has support for pre-processor languages like Sass, CoffeeScript and Erb. It also handles fingerprinting, which allows assets to be cached according to their contents. Before talking more about the asset pipeline, its important to understand why you would want these features.

The purpose of concatenating and compressing assets is to reduce the number of files and the size of files. Reducing the number of files means that the browser has to make fewer requests. Browsers can only make a limited number of requests in parallel (modern web browsers can perform 6-8). Reducing the size of asset files means that there are less bytes to send over the network. Both of these features allow the browser to load pages faster.

Using the asset pipeline is simple. A new Rails application has the asset pipeline enabled by default. Internally, Rails uses a gem called sprockets, which is responsible for concatenating all of the asset files into one master JS and CSS file. Sprockets uses a manifest file to determine which assets to serve. Here is what a manifest file looks like:

# app/assets/javascripts/application.js
//= require core
//= require projects
//= require tickets

From this manifest file, Rails will generate the following script tags:

<script src="/assets/core.js"></script>
<script src="/assets/projects.js"></script>
<script src="/assets/tickets.js"></script>

In development assets are served as separate files, to help with debugging. In production, all of these assets will be compiled into a single file. In this example all three of the JS files specified in app/assets/javascript/application.js will be compiled into the following script tag:

<script src="/assets/application-908e25f4bf641868d8683022a5b62f54.js"></script>

The assets files have all been concatenated into a single file and the MD5 fingerprint has been added to the filename. Not only that, if you inspect the file you will see that the contents have been compressed (minified):

The purpose of the MD5 fingerprint is to make each filename unique, based on its contents. This allows browsers, CDNs and ISPs to cache the file. When the content changes, the fingerprint will change, causing the cache to bust.

Alternatives to the asset pipeline

There are many alternatives to the asset pipeline, tools like Grunt, Gulp & Webpack (and many more).

Grunt

Grunt is a task runner that allows you to automate tasks like concatenating assets, compressing assets and running unit tests. Grunt supports a wide range of tools including CoffeeScript, SASS and LESS. When you run the grunt command it runs the configuration that you have specified in your Gruntfile. Unlike the asset pipeline, Grunt requires some configuration. Lets say that you want to compress (minify) your JS files, You would need to write a Gruntfile that looks something like this:

module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    uglify: {
      options: {
        banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
      },
      build: {
        src: 'src/<%= pkg.name %>.js',
        dest: 'build/<%= pkg.name %>.min.js'
      }
    }
  });

  // Load the plugin that provides the "uglify" task.
  grunt.loadNpmTasks('grunt-contrib-uglify');

  // Default task(s).
  grunt.registerTask('default', ['uglify']);

};

What strikes me about using a tool like Grunt is that you’re not going to get any help like you get with the asset pipeline. The asset pipeline is ready to go, right out of the box – you don’t even have to switch it on, its turned on by default.

I don’t have time to talk about all of the different JS tools (Webpack, Gulp ect) in this blog post, the point here is to decide whether to use the asset pipeline or a tool from the JavaScript ecosystem. I believe the points I’ve made about Grunt apply to other JavaScript tools. Some tools may be simpler than the Grunt but all will require some configuration, unlike the asset pipeline which requires zero configuration.

Using a tool like Grunt is definitely more work upfront than using the asset pipeline but I can think of a couple of advantages:

  1. It’s going to be a lot easier to separate your front-end logic into a separate codebase, because the code bundling logic is already outside of Rails
  2. You’ll find it easier to modify the code bundling logic because you’ve had to configure all of it yourself. As a pose to the asset pipeline where everything is set up for you automatically

Which should you use

The advantage of the asset pipeline is that it requires zero configuration. Rails will concatenate assets, compress asset, add MD5 fingerprints and support all of the Rails pre-processors (CoffeeScript, Sass, Erb) out of the box. If you intend to stick within the Rails ecosystem then using the asset pipeline is a great choice.

Since the time that Rails was created there has been an influx of JavaScript frameworks. If you are using a front-end framework, I believe it is a good idea to separate the front-end and back-end, at the start of the project. If you’re using a JavaScript framework then you should be using a tool like Grunt or Gulp to handle your assets.

I’ve worked with a number of Rails applications that have a JavaScript framework in the same codebase as their Rails app. I’ve found these applications to be difficult to manage. I’m in favour of a clean separation between front-end logic and back-end logic. They should be two separate codebases.

Summary

If you are starting from scratch and you think that your app will not require much front-end logic then stick with Rails and use the asset pipeline. For anything else, I recommend creating a separate codebase and using a front-end framework.

If you’re using a front-end framework and you’ve got everything bundled into the same codebase, you may want to consider moving away from the asset pipeline. It’s likely that you’ll want to separate the front-end and back-end in the future. If you start removing the dependencies early then it will be less painful down the road.