Asset managing with Rails 3 (on Heroku) (Jammit, AssetHat, Rack PageSpeed) - ruby-on-rails

I am interested in the pros and cons of the different tools for managing assets in Rails 3.0.x (especially on Heroku).
There are already some older questions regarding this topic, but in the meanwhile there are some new tools available.
I am especially interested in these tools:
Jammit
AssetHat
Rack PageSpeed
Jammit seems to can do everything that AssetHat can do and is also longer available. So where does AssetHat fit in?
Rack PageSpeed seems to do everything on the fly by directly working on the server response. Did you experience any performance issues by doing that? Would you recommend it over the other two solutions?

Hey there, I'm the author of AssetHat. Minification and concatenation are among the easiest performance boosts to implement; these features are common to Jammit, AssetHat, and rack-pagespeed. Rails has supported concatenation for a long time now (though it's done at runtime, rather than during deployment), and it's no surprise that Rails 3.1 supports both minification and concatenation during deployment.
The remaining features are what make each of these asset managers interesting. For example, Jammit is useful if you want to embed images and font files directly into your stylesheets. rack-pagespeed is also handy if you want to keep all your optimizations in a completely separate layer.
Inlining assets into CSS is great for static pages where stylesheets change infrequently. However, if your site is under active development, and the stylesheet changes even a tiny bit, the user's browser has to re-download the whole thing—including inline images and fonts that probably didn't change. It depends on the nature of your project.
If your assets are too big to inline or concatenate, AssetHat helps optimize for CDNs and parallel loading:
It takes great advantage of CDNs, whether it's Google's CDN, cdnjs (which uses Amazon's servers), or another CDN of your choosing. For example, just add <%= include_js :jquery %> to your layout (and a version number in a config file) to load jQuery from Google's CDN. If you're in dev mode and have a local copy of jQuery, that loads instead—easy offline dev.
AssetHat can rewrite stylesheets' image URLs to use your CDN instead. This reads from your config.action_controller.asset_host setting, and is done at deploy time. Your original CSS is left untouched.
If you have several JS files to load, it's sometimes faster to load them in parallel than to concatenate them (i.e., force them to load serially). You can switch on LABjs mode easily: <%= include_js 'big-file-1', ..., 'big-file-n', :loader => :lab_js %>. If you don't have a copy of LABjs locally, or if you're in production, LABjs loads from Amazon's servers via cdnjs.
By using CDNs like Google's or Amazon's, your users can load more assets in parallel (because there are more hostnames), enjoy greater speed, and sometimes, not even need to download assets at all (e.g., if they already loaded Google's copy of jQuery via someone else's website).
I've used AssetHat on Heroku by setting my deploy script to simply run rake asset_hat:minify (to minify and concatenate CSS/JS), commit those changes to my repository, then do the actual deployment.
In case you haven't seen these already, you might be interested in:
a longer walkthrough of AssetHat's features
the official website
the technical readme
the extensive docs
If you need help setting it up, or have any other questions, feel free to message me on GitHub (rondevera) or Twitter (#ronalddevera).

Jammit won't work out of the box on Heroku as far as I know. One option seems to be to use the Heroku Jammit plugin to manage your assets - https://github.com/chebyte/heroku-jammit.
Alternatively, Jammit can be configured to output to /tmp: http://geekninja.blogspot.com/2011/04/making-jammit-jam-with-heroku.html
Rails 3.1 will include Sprockets to handle asset packaging, I think that's worth considering.

I am currently using jammit on heroku, together with amazon s3, and it works like a charm :)
I can't say much about the others tools because I have not used them.
Which one did you pick, in the end?
Fernando.

Related

Should I use Sprockets in Rails?

When I'm testing my app on a vps through sublime and sftp, these Sprockets cache files always take forever (figuratively) to sync. What are the consequences of disabling Asset Pipeline? Will my app perform noticeably poorly?
What are the consequences of disabling Asset Pipeline? Will my app perform noticeably poorly?
Yeah, the asset pipeline is there for a reason, quoting the guide:
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.
The concatenation of assets leads to fewer HTTP requests (connection setups) which is, at least for HTTP 1.1 considered as a best practice. Minification speaks for itself I guess. Take a look at the guide to get a full grasp of the consequences.
I'm not sure what exactly you mean with sprocket cache files and which environment (as in Rails.env) you're using on your VPS.
You can also compile the assets on the VPS, which might be quicker than uploading. (See compile/precompile section in the guide).
For testing purposes you could also run in the development environment, where the assets will be compiled on demand.

Can't I use Polymer.js via CDN in rails app?

I want to add frameworks like AngularJS, Bootstrap and polymer JS into my rails app. Problem with the gems is they are unstable with new versions and they even stop developing gems(which leads to failing of one gem which depends on another)
So I just want to add those frameworks directly into the application root html file via CDN(offered by the vendor). Is that a good practice? Will it cause any future problems in production environment?
Yes, if you are using reliable CDN's (and those offered my vendors can be treat as one) it may even bring you some improvements in the production enviromnent, e.g.:
those assets will be often already cached on your user's machines
it circumvents browsers limit the number of concurrent connections from the same domain (as your app)
On the flip side, on your dev enviromnent you'll have to wait a liiitle bit more for the website to load those assets comparing it to loading them from localhost ;)
if you dont use CDN,you have much control over the assets ,as they might change/update or sometimes the url can be down :( in worst case scenario..so i suggest using local assets if there is large dependency and for small dependency ...you may use cdn. :)
use this to set up polymer js onlocal.

Rails: What's the advantage/disadvantage of putting scripts and stylesheets directly in public folder?

So that I could take advantage of all the already well developed front-end tools like requirejs, bower and grunt... It's just that so many of them somehow get crippled going with rails.
Primary advantages:
It is easier to load third party scripts this way. It is always possible and sometimes easy to put these through the asset pipeline, but it is also often tedious and you lose bower.
Scripts in public will not be digested, so they can be loaded by non-rails pages easily. For example, you use a javascript file on your site, and also need to load it on another, e.g., PHP site, or need to allow other people to load your script for an embedded API, etc... then you'll need to serve from public.
Primary disadvantages:
Because you're not using the asset pipeline you lose:
Asset combining and compression. Asset pipeline CSS and Javascript will be loaded in a single HTTP request each, and the content can be minified. This makes first page load on your site faster, especially if you have lots of client code or a site that needs to be super snappy for occasional visitors.
Digesting. The asset pipeline protects you 100% from cache vagaries and potentially having different users seeing your site with different version of your assets. Once you deploy, every visitor will get the new assets.
Relatively automatic etagging. Once those visitors get the new assets, their clients will generally cache them for a long time. Rails can afford to let assets cache essentially forever because digesting ensures you're not punished for this later.
So there are pros and const both ways and neither is right or wrong.
It's just that so many of them somehow get crippled going with rails
Pipeline
The reason is you're not meant to use the likes of Grunt etc with Rails. Rails' asset pipeline is only meant to contain the files which can be precompiled & used directly in your application:
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.
This will typically mean compiled third party JS/CSS files, and your own application JS/CSS files. I don't see how something like Grunt would provide any benefit to this? All it does it create a way for you to manage dependencies, versioning & source of particular assets?
--
Public
Using the files in your public folder isn't such a big deal. One of the most prominent things it does do is to exclude those particular files from the file digest processs, allowing you to use the likes of endpoints (scripts) which can be accessed by other services (outside the scope of routes.rb)
A good example of this is when we created an analytics system, and put the analytics.js into the public folder, so all the widgets could access it. This allowed other sites to access this file, regardless of the state of the asset pre-compilation.
One caveat to this would be you could perhaps have some way to store a "pseudo" file in the public folder, with it routing dynamically (with ERB) to the precompiled equivalent, but I've got no experience with this
--
Pipeline
The benefits of keeping your assets inside the asset pipeline, as stated by gwcoffey, are:
They will be compiled as you design (I.E primarily into application.js, but also into any other files you define too)
You don't need to worry about versioning (every precompile is basically a way to better the version without worrying about grunt etc)
You can include as many dependencies as you want - meaning you're able to create a totally modular set of assets which can be used throughout your app; rather than single scripts which will have their own dependency base
Recommendation
Unless you maintain third-party scripts which need dependencies to run, I would not recommend using Grunt for Rails. If you develop your own JQuery / Javascript scripts, by all means run them through Grunt etc; but for use in your app, I'd steer clear
Hope that helps!

How can I test whether or not my gzipped css file is being served?

I'm using jammit to embed data-uri's in my rails app. This is not a jammit or rails specific question though.
For each css file generated, jammit creates two versions i.e.:
style-datauri.css (75KB)
style-datauri.css.gz (40KB)
I know that everything is working because my production app is serving data-uri's to firefox and chrome, and whilst I don't have access to IE, screenshots from browsershots suggest that all is well.
Q1: How can I test that the gzipped version of my stylesheet is the one which is being served to the browser? I care because it's a significantly smaller file.
(I guess I could change the font-size in the non-gzipped css file and see what happens but I'm hoping there's a simpler way - perhaps using curl or something)
Q2: The app is hosted on heroku and I know from their docs that they gzip everything for you, but I'm also told that jammit uses the highest compression level and that heroku don't. Will my file be gzipped twice then? Once by jammit, and then once more by nginx?
Q1
You can inspect the HTTP headers to guess what's happening; nginx can be told to serve gzipped version of your css or to create a zipped version on the fly, but I am not sure you can easly say what is being server from the client point of view.
Q2
Heroku sports a powerful caching / optimizing frontend system powered by nginx and Varnish; they will be happy to explain you how to make your app consuming less resources.
BONUS
Loading the home page of your web app my browser downloads over 1MB of data; to make it snappier you can lazy load images via Javascript.

What are the pros and cons of asset_packager and Jammit?

At a glance they seem to be pretty much the same solution to the same problem, but Jammit must have some key difference or improvement that I haven't picked up on, or its author would have just used asset_packager. :-)
Can anyone enlighten me?
Sure. Here's some of the main differences:
Instead of using simple Ruby-based CSS and JS minifiers, Jammit makes it easy to use either the YUI Compressor or the new Google Closure Compiler to compress your assets.
Instead of having to specify each file individually, Jammit uses an ordered list of directory globs to define an asset package. This means you can say things like: give me jQuery first, then everything in vendor, then all my models, then all my UI...
workspace:
vendor/jquery.js
vendor/*.js
models/**/*.js
view/workspace/*.js
Jammit supports JavaScript Templates, so whether you're using Prototype or Mustache or Underscore templates, you can maintain your JavaScript views right alongside your Rails views, and have them bundled into a single package, available in the browser.
Jammit supports image embedding, using Data-URIs for browsers that support them, and MHTML for IE7 and below. Enabling it allows you to embed all of your UI chrome and small icons right into your CSS, so that instead of 50 HTTP requests, your browser makes just one.
When you install the gem, Jammit includes the jammit command-line utility, which you can use to prebuild all of your assets and pre-gzip them at the highest compression level. Gzipping at --9 gives us about a 30% reduction in size for our assets, over the default gzip --2 (which is closer to what you'll get by default if you're gzipping on-the-fly). You should be using both, but only gzipping on-demand for dynamic requests.
Hope that helps with the differences -- for everything else, there's http://documentcloud.github.com/jammit/

Resources