The goal of the asset pipeline is to:
- Compress files so they are as small as possible
- Smaller files load faster
- Reduce the number of files transferred to the client
- By combining files
- CSS files are combined into a single file
- Javascript files are combined into a single file
- By caching files in the browser
- By combining files
<head>
<title>Load all the things!</title>
<script type="text/javascript" src="/vendor/jquery.js"></script>
<script type="text/javascript" src="/vendor/underscore.js"></script>
<script type="text/javascript" src="application.js"></script>
</head>
That's 3 different requests to the server, for 3 different javascript files. Ouch!
There's got to be a better way!
Your application can be configured to "cache" common javascript and css files in the client's browser.
Cached files don't need to be requested on every page load. They're already there, ready to go: meaning less wait time and faster page loads.
But how does the browser know when to update a cached file? What if you changed the file and the browser is using an older version?
We need a way to "bust" the cache!
Cache Busting with Fingerprints
In Rails, assets are given a "fingerprint" that changes every time the file is updated (almost like a timestamp).
For example, application.js
file, with a fingerprint looks like this:
application-908e25f4bf641868d8683022a5b62f54.js
- If the fingerprint is the same, the browser simply uses its cached copy.
- If the fingerprint has changed, the browser requests the new version of the file (and then caches it!).
- This is called "cache busting"
What's the difference between jquery.js and jquery.min.js?
Let's do a quick comparison on the command line:
# uncompressed jquery file
curl http://code.jquery.com/jquery-2.1.4.js | wc
# lines words bytes
# 9210 37959 247597
# compressed jquery file
curl http://code.jquery.com/jquery-2.1.4.min.js | wc
# lines words bytes
# 4 1305 84345
A CDN is a "content delivery network" and a handy way to deliver common "vendor" or "third party" libraries to your application. It's common to use a CDN for jQuery, Bootstrap, Undescore, Handlebars, etc.
But is it fast?
If a common file, like jQuery is delievered via CDN it is likey:
1. cached in your browser
2. cached by your ISP (Internet Service Provider)
3. dispatched from a nearby server
But is that faster than just sending 1 javascript file from your own server?
Could be! You'll have to make a decision about whether you want to host third party libraries (like jquery), or if you want to use a public CDN.
How we used to require files (manually):
<head>
<title>Load all the things!</title>
<script type="text/javascript" src="/vendor/jquery.js"></script>
<script type="text/javascript" src="/vendor/underscore.js"></script>
<script type="text/javascript" src="application.js"></script>
<link rel="stylesheet" href="/vendor/bootstrap.css">
<link rel="stylesheet" href="application.css">
</head>
How rails requires files (using the asset pipeline):
<script src="/assets/application-908e25f4bf641868d8683022a5b62f54.js"></script>
<link href="/assets/application-4dd5b109ee3439da54f5bdfd78a80473.css" rel="stylesheet" />
That's just two files!
In rails, instead of manually adding all those script tags, you're going to take advantage of app/assets/javascripts/application.js
. Inside it there's a weird looking comment called a manifest
:
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require_tree .
Actually, It's not a comment!. It's instructions saying which files need to be loaded in the head
of your html, and in what order.
It will look for the name of the file (e.g. "jquery") in the following directories:
app/assets/
-- application specific codelib/assets/
-- custom librariesvendor/assets/
-- third party libraries
So far we've been working on our applications in development. You may have noticied that when you create a rails application it has three databases: development
, test
, and production
.
The assets pipeline is designed for production applications. That's when we care about speed!
To turn your many javascript and css files into one javascript file and one css file, you need to "precompile" your assets.
Precompiled assets live in public/assets/
. Right now it's an empty folder!
We need to run:
rake assets:precompile
Now look inside public/assets/
and you'll see minified and fingerprinted versions of your assets, ready to be compiled into a single file.
<script src="/assets/application-908e25f4bf641868d8683022a5b62f54.js"></script>
<link href="/assets/application-4dd5b109ee3439da54f5bdfd78a80473.css" rel="stylesheet" />
To run your application "in production" you can add the following flag:
rails s -e production
To destroy all your precompiled assets, simply run:
rake assets:clobber
Warning: Watch out that you're not using OLD precompiled asssets! If you're not seeing your changes in production, you likely need to update your precompiled assets.
For more info, hit the docs: Rails Guides: Asset Pipeline