Ā¶ ā
AssetHatLoad CSS and JS faster. Your assets are covered.
With Railsā default asset caching, CSS and JS are concatenated (not even minified) at runtime when that bundle is first requested. Not good enough. To make your pages load faster, AssetHat can automatically:
-
Easily minify and bundle CSS and JS to reduce file sizes and HTTP requests. Do this on deploy, and avoid any performance hit at runtime.
-
Load popular libraries from the JS community ā like jQuery, YUI, and Dojo ā from {Googleās CDN} when in production, or from localhost in development. Itās as simple as
<%= include_js :jquery %>
to load straight from Google. -
Load plenty of JS files in parallel in {LABjs}[http://labjs.com/] mode. When calling
include_js
, just add:loader => :lab_js
. -
Force image URLs in your CSS to use CDN subdomains (including SSL support), not just the current host.
-
Add an imageās last Git commit ID to its CSS URLs to bust browser caches (e.g.,
/images/foo.png?ab12cd3
).
After setup, you can use this in your layouts and views:
<%= include_css :bundle => 'application' %> <%= include_js :jquery, :bundles => ['plugins', 'common'] %>
Which expands into:
<link href="/stylesheets/bundles/application.min.css" media="screen,projection" rel="stylesheet" type="text/css" /> <script src="/javascripts/jquery-1.x.x.min.js" type="text/javascript"></script> <!-- In production, jQuery loads from Google's CDN instead. --> <script src="/javascripts/bundles/plugins.min.js" type="text/javascript"></script> <script src="/javascripts/bundles/common.min.js" type="text/javascript"></script>
Donāt have your own copy of jQuery? AssetHat detects this and knows how to load jQuery from Googleās CDN instead, whether youāre in development or production.
Add this to your deploy script, and your CSS/JS will be optimized automatically:
rake asset_hat:minify
Tested with Rails 3 and Rails 2.3.x (with Bundler). For a quick overview, see the AssetHat website. To see how AssetHat performs in production, check some stats. For the gritty details, check the complete docs and change history.
Ā¶ ā
InstallationĀ¶ ā
Rails 3.x-
Add to your appās Gemfile:
gem 'asset_hat', '0.x.x'
-
Command-line:
bundle install
Ā¶ ā
Rails 2.3.x-
Add the gem:
-
If youāre using Bundler 0.9+:
-
Add to your appās Gemfile:
gem 'asset_hat', '0.x.x'
-
Command-line:
bundle install
-
-
If youāre using Rails 2.3.xās
config.gem
:-
Add to your appās
config/environment.rb
:config.gem 'asset_hat', :version => '0.x.x'
-
Command-line:
gem install asset_hat
-
-
-
Add to your appās Rakefile:
require 'asset_hat/tasks'
Ā¶ ā
Quick start & configuration-
In all of your layouts and views, change
stylesheet_link_tag
toinclude_css
, and changejavascript_include_tag
toinclude_js
. (Donāt worry, these helpers use the same arguments as Railsā helpers. Nothing will break.) -
Create the default config file:
rake asset_hat:config
-
In your app, open the new file at
config/assets.yml
, and set up your CSS/JS bundles according to that fileās example. -
In your layouts and views, switch to the new bundles. For example, if you originally had this:
<%# app/views/layouts/application.html.erb: %> <%= stylesheet_include_tag 'reset', 'application' %>
Then youāll now have:
# config/assets.yml: css: bundles: application: ['reset', 'application'] <%# app/views/layouts/application.html.erb: %> <%= include_css :bundle => 'application' %>
-
Add this to your deployment script:
rake asset_hat:minify
This minifies all of the CSS/JS files listed in
config/assets.yml
, concatenates the minified code into bundle files, and adds CDN asset hosts and cache-busting commit IDs to image URLs in your CSS.Any previously minified bundles are overwritten; your original CSS/JS files remain untouched. Bundles are created as new files in
public/stylesheets/bundles/
andpublic/javascripts/bundles/
.If youāre using a CSS/JS layer like SASS or CoffeeScript, be sure to compile/transpile to regular CSS/JS before running
rake asset_hat:minify
. (When AssetHat is ready for Rails 3.1,rake asset_hat:minify
will automatically start withrake assets:precompile
.)
Ā¶ ā
Advanced configurationIf you manage deployments with Capistrano, see the gemās packaged example at lib/asset_hat/capistrano.rb[https://github.com/mintdigital/asset_hat/blob/master/lib/asset_hat/capistrano.rb]
.
If your stack uses Unicorn, youāll want to configure it so that assetsā commit IDs are precached only once. See the gemās packaged example at lib/asset_hat/unicorn.rb[https://github.com/mintdigital/asset_hat/blob/master/lib/asset_hat/unicorn.rb]
.
If you want shorter output during deployments, you can use ārake asset_hat:minify FORMAT=short` (one output line per bundle) or `FORMAT=dot` (one output line total) in your deploy script.
Additional settings are supported in config/assets.yml
:
-
engine
: Indicates how CSS and JS are minified; omit this setting to use the defaults. By default, CSS is minified with rgrove/cssmin (a Ruby port of Lecomteās YUI Compressor and Schlueterās PHP cssmin), and JS is minified with rgrove/jsmin (a Ruby port of Crockfordās JSMin).If youād prefer to have slightly more readable code for debugging purposes, you can switch both the CSS and JS engines to
weak
. However, theweak
engines donāt save as many bytes. -
vendors
: Configures third-party JS thatās loaded from a CDN or other external source. The following example configures jQuery and jQuery UI for use throughout the app:js: vendors: jquery: version: 1.5.2 jquery_ui: version: 1.8.12 remote_url: http://cdn.example.com/js/jquery-ui-1.8.12.min.js remote_ssl_url: https://cdn-ssl.example.com/js/jquery-ui-1.8.12.min.js
Configuration keys per vendor:
-
version
: Sets the default version across the app. In the example above,<%= include_js :jquery %>
uses version 1.5.2 by default. You can override this for special layouts/views with<%= include_js :jquery, :version => '1.3.2' %>
. -
remote_url
,remote_ssl_url
: By default, vendor JS will load from Googleās CDN in production (or any environment whereconfig.action_controller.consider_all_requests_local
is set tofalse
). If the original request to your app used SSL, the vendor JS will also load from Googleās CDN via SSL. If you prefer to use a different CDN, specify its SSL/non-SSL URLs, and the appropriate URL will be used per request.
A full list of supported vendors is in the
AssetHat::JS::Vendors
module. -
Ā¶ ā
SSL configurationWhen you request a page via SSL, some browsers (euphemism for āIEā) show errors if any assets ā stylesheets, JS files, images ā are served without SSL.
AssetHat plays well with SSL pages that load assets from a CDN. Put this in config/environments/production.rb
or similar:
config.action_controller.asset_host = Proc.new do |source, request| "#{request.protocol}cdn#{source.hash % 4}.example.com" # => 'http://cdn0.example.com', 'https://cdn1.example.com', etc. end
This switches to a different CDN URL if the request used SSL. When you run rake asset_hat:minify
at deploy time, AssetHat detects this configuration, and generates special SSL versions of each stylesheet that also load images from CDN via SSL. (Non-SSL pages still get non-SSL stylesheets.)
Ā¶ ā
UsageIn your layouts and views, instead of these:
<%= stylesheet_link_tag 'reset', 'application', 'clearfix', :media => 'screen,projection', :cache => 'bundles/application' %> <%= javascript_include_tag 'plugin-1', 'plugin-2', 'plugin-3', :cache => 'bundles/application' %>
Use these:
<%= include_css :bundle => 'application' %> <%= include_js :bundle => 'application' %>
These turn into:
<link href="/stylesheets/bundles/application.min.css" media="screen,projection" rel="stylesheet" type="text/css" /> <script src="/javascripts/bundles/application.min.js" type="text/javascript"></script>
Have an enormous app? You can integrate gradually, using AssetHat alongside Railsā default asset caching.
If your environment has config.action_controller.perform_caching
set to true
(e.g., in production), the layout/view will include minified bundle files. Otherwise, the separate, unminified files will be included, based on the bundle contents you define in config/assets.yml
.
If your environment has config.action_controller.asset_host
pointing to a CDN, your CSS/JS files will load from there. If your configuration supports using the CDN via SSL (see the section āSSL configurationā), SSL requests will also load CSS/JS files via SSL.
Ā¶ ā
Advanced usageYou can also include single files as expected:
<%= include_css 'reset', 'application' %> <%= include_js 'plugin.min', 'application' %>
Or include multiple bundles at once:
<%= include_js :bundles => %w[plugins common] %>
When including multiple bundles at once, this yields one <link>
or <script>
element per bundle.
Ā¶ ā
LABjs modeSay youāre loading several JS bundles. However, because there are so many, you decide to try a popular script loader like LABjs to see how much it improves performance. Hereās how itās done the old Rails way:
<%= javascript_include_tag 'LAB-1.2.0.min.js' %> <script> $LAB. script('/javascripts/jquery-1.6.1.min.js').wait(). script('/javascripts/common.js').wait(). script('/javascripts/search.js').wait(). script('/javascripts/app.js').wait(); </script>
What a hassle. With AssetHat, just set up a bundle in config/assets.yml
:
js: bundles: app: - common - search - app
Ready to go. Hereās how to load jQuery and your bundle normally:
<%= include_js :jquery, :bundle => 'app' %>
And hereās how to switch on LABjs mode:
<%= include_js :jquery, :bundle => 'app', :loader => :lab_js %>
Add your preferred jQuery and LABjs versions to the config file if you havenāt already, and thatās it. If you donāt have a copy of LABjs locally, AssetHat knows how to instead load it from cdnjs, which uses high-speed Amazon Cloudfront servers.
This is just the most common LABjs use case. If you want to fine-tune it even further, you can have the best of both worlds:
<%= include_js :lab_js %> <script> $LAB. script('<%= include_js :jquery, :only_url => true %>').wait(). script('<%= include_js "common", :only_url => true %>'). // Non-blocking script('<%= include_js "search", :only_url => true %>').wait(). script('<%= include_js "app", :only_url => true %>').wait(); </script>
In this example, common
is not a dependency for search
, so allow either to execute as soon as possible ā whichever happens to load first ā rather than always forcing common
to execute first.
Ā¶ ā
Bundle tipsDonāt go overboard with huge bundles:
-
Mobile browsers may not cache CSS/JS files that are too large, regardless of gzipping. Check the latest specs for each mobile browser you support.
-
You might want to put plugins (rarely changed) in one bundle, and application code (frequently changed) in another bundle. This way, when the app code changes, the browser re-downloads only the new app code, and uses the cached plugin code.
-
Regardless of code-change frequency, itās sometimes faster to split a bundle in half, and load each half in parallel (i.e., two HTTP requests instead of one). LABjs mode can help with loading several smaller bundles in parallel. Your own tests will tell whatās optimal for your situation.
Ā¶ ā
More info-
Released under the MIT license.
Ā¶ ā
ContributingHave an idea, problem, or bug report? Send a pull request! Please base pull requests on the ādevelopment` branch, not the `master` branch.
Contributors:
What is best in AssetHat?Ā¶ ā
-
To crush your assets;
-
See them bundled before you; and
-
Hear no more lamentation about slow page loads.