Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Asset Fingerprint Plugin for Ruby on Rails - allows you to use md5 or timestamps in query string or in asset filenames as suggested by Google Page Speed
Ruby
branch: master

README.md

Asset Fingerprint

Asset Fingerprint is a Ruby on Rails plugin (supports Rails versions 2.2.x & 2.3.x, for Rails 3+ see Rails Version Support) to fingerprint asset files using md5 checksum (or timestamp or anything else you like) in file names to improve cacheability compared to the default Rails asset caching strategy.

So, instead of asset paths like /images/logo.png?1234567890 you can have fingerprinted asset paths like /images/logo-fp-839b180ff39a24f8d6e0ee70e4c40fed.png with no query string.

The server knows how to handle the fingerprinted asset paths using rewrite rules or symlinks, as explained in file_name path rewriting.

At time of writing, the default configuration used by the plugin is based on guidelines given at Google Page Speed.

The plugin alters AssetTagHelper so the relevant helper methods (image_path, image_tag, stylesheet_link_tag, etc.) generate the correct fingerprinted URLs.

Asset Fingerprint can also be customized in any other way, for example if you wanted to use the default Rails asset caching strategy of putting file timestamps in the query string, then you can, however…

File timestamps are not recommended as fingerprints as these are often inconsistent between deployments when a file has not changed. This means your app may not take full advantage of asset caching. Reasons for timestamp inconsistency include:

  • Multiple app servers checking out files at different times
  • Git does not preserve file timestamps (it really doesn't)
  • Subversion not configured to preserve file timestamps
  • Generated asset files (e.g. compressed css and js bundles)

In all of these cases the md5 checksum does not change unless the file contents have changed, so using an asset file's md5 checksum as its fingerprint is often a better option than a file timestamp.

Putting fingerprints in the query string is also not recommended as some caching proxies are allegedly incorrectly configured to ignore query string parameters. File name fingerprinting gets around this problem.

Rails Version Support

Getting started

  1. Install the plugin at vendor/plugins/asset_fingerprint in your app.
  2. Then you must create a config/initializers/asset_fingerprint.rb file and put the following require statement in it: require 'asset_fingerprint/asset_tag_helper'
  3. By default, the plugin will give your app asset paths with maximum cacheability, i.e. using md5 fingerprints as part of the asset file name, however if you do not want this, then you can change it. For example if you want to use timestamp fingerprints instead of md5 fingerprints, or you want to put the fingerprint in the query string instead of the file name, then you can add one or both these lines to the initializer script we just created:

    AssetFingerprint.fingerprinter = :timestamp # default is :md5

    AssetFingerprint.path_rewriter = :query_string # default is :file_name

Write your own fingerprinters and path_rewriters

If you need to, it is simple to write your own fingerprinters and path_rewriters and configure them in the initializer script. View the source to see how this can be done.

file_name path rewriting

The :file_name path rewriter is used by default and changes the file name of the asset paths generated by rails helpers such as image_tag, image_path, stylesheet_link_tag, etc.

Your app will need to know which asset file to serve for a given rewritten file path as the rewritten paths do not correspond to a real file.

Luckily getting your app to do this is simple in most cases, two options are presented below, a Server Rewrite and a Generate Symlinks option.

You can use both methods for different environments within the same app. For example, I've previously used the server rewrite option in development to save muddying my dev environment with lots of symlinks, and in the same app used the symlink option in production so I could use Passenger's high performance option (which required that Apache Rewrite is not used).

Server Rewrite

If you decide to use the Server Rewrite method, add this line to the initializer script:

AssetFingerprint.asset_files_served_by = :server_rewrite

Then, assuming you are using Apache, add one of these rewrite rules to get it to serve the correct asset file for a fingerprinted path:

# For md5 fingerprints
RewriteRule ^(.+)-fp-[0-9a-z]{32}(.*)$ $1$2 [QSA,PT,L]

 

# For timestamp fingerprints
# (you should check that the timestamps returned by your production operating
# system are 10 digits long. If they are not, change the {10} in the regex
# below to the correct length.)
RewriteRule ^(.+)-fp-[0-9]{10}(.*)$ $1$2 [QSA,PT,L]

If you're not using Apache, then adapt the rules above for your server.

P.S. User-submitted rewrite rule for nginx rewrite "^(.+)-fp-[0-9a-z]{32}(.*)" $1$2 last;

Generate Symlinks

This option creates a symlink for each asset file, where the symlink is the rewritten filename, e.g. the asset file images/logo.png would get a symlink like images/logo-fp-1234567890.png pointing to it.

The symlink option is recommended if you think symlinks will give you better performance than rewrite rules.

By default, the plugin generates symlinks on-the-fly, however you can generate all the symlinks ahead of time at deployment using rake:

rake asset_fingerprint:symlinks:generate

If you use this rake task you'll want to stop symlinks from being generated on-the-fly. Add this setting to your initializer script:

AssetFingerprint.symlink_on_the_fly = false

Call the rake task like so (you may want to do this with capistrano):

rake asset_fingerprint:symlinks:generate RAILS_ENV=the_env

If your app has asset files or directories in public/ that are not any of these defaults: ['favicon.ico', 'images', 'javascripts', 'stylesheets'] then add this setting to the initializer script and customize as needed:

AssetFingerprint.asset_paths = ['my-custom-image.png', 'my-custom-dir', 'favicon.ico', 'images', 'javascripts', 'stylesheets']

The AssetFingerprint.asset_paths setting is used by the rake task to decide which files to symlink. If you specify directories, it will search them recursively for asset files symlinking as it goes. You only need to specify exact file names if they are immediate children of public/, like public/favicon.ico.

Using the rake task is recommended to save the overhead of generating the symlinks on the fly during user requests in a production environment.

Tips

  • To remove the generated symlinks call rake asset_fingerprint:symlinks:purge
  • By default the plugin will cause symlinks to be generated in your development environment (take care not to commit the symlinks to your repository) until you set AssetFingerprint.symlink_on_the_fly to false.

Contributors

Copyright (c) 2010-2013 Eliot Sykes, released under the MIT license

Something went wrong with that request. Please try again.