Rails Asset Pipeline and Digest Values

Rails asset pipeline and digest values

Grabbed from rails guides

When a filename is unique and based on its content, HTTP headers can
be set to encourage caches everywhere (whether at CDNs, at ISPs, in
networking equipment, or in web browsers) to keep their own copy of
the content. When the content is updated, the fingerprint will change.
This will cause the remote clients to request a new copy of the
content. This is generally known as cache busting.

The technique that Rails uses for fingerprinting is to insert a hash
of the content into the name, usually at the end. For example a CSS
file global.css could be renamed with an MD5 digest of its contents

How can I determine the MD5 digest of a given asset in the Rails asset pipeline?

As someone mentioned in the comments, appending a hash to the asset paths is a default part of the asset pipeline.

In production, Rails inserts an MD5 fingerprint into each filename so that the file is cached by the web browser

You can read more about fingerprinting in the asset pipeline here. Rails uses Sprockets to compile assets. The fingerprinting comes as part of Sprockets process.

You can use Sprockets' find_asset method, passing in a logical path to your asset to get a Sprockets::BundledAsset instance. For example

[1] pry(main)> Rails.application.assets.find_asset('application.js')
=> #<Sprockets::BundledAsset:0x3fe368ab8070 pathname="/Users/deefour/Sites/MyApp/app/assets/javascripts/application.js", mtime=2013-02-03 15:33:57 -0500, digest="ab07585c8c7b5329878b1c51ed68831e">

You can call digest_path on this object to get it's MD5 sum appended to the asset.

[1] pry(main)> Rails.application.assets.find_asset('application.js').digest_path
=> "application-ab07585c8c7b5329878b1c51ed68831e.js"

With this knowledge you can easily create a helper to return the digest_path for any asset in your application, and call this helper from within your .js.erb files.

Rails: How do I force a new asset digest on ALL assets?

I found the only way to force expiration of assets and get them recompiled was to add the following in my config/environments/production.rb

config.assets.version = '1.1' #This currently doesnt work as intended so use
config.assets.prefix = '/production'

Then bundle exec rake assets:precompile RAILS_ENV=production

Rails 4 and Sprockets 3 don't quite get along as per the thread here thus the versioning not working as intended: https://github.com/rails/sprockets-rails/issues/240

Rails 4 selective asset digest

All files get digested. In Rails 3 all files also had a copy without digest but this was removed in Rails 4. Now you're supposed to have non digested assets in /public. A workaround is to create a rake task which copies the assets. More details can be found in https://github.com/rails/sprockets-rails/issues/49 in there is also a monkey patch to restore the old behavior.

Referencing rails assets without the digest?

You can try asset_path('app.js', :digest => false) or disable digest in the prodution env:

# config/environments/prodution.rb
config.assets.digest = false


Rails pipeline

Rails 4 asset pipeline doesn't overwrite assets with asset_path references to other assets

A solution was suggested here which involves using the depend_on or depend_on_asset directive. In my case adding this to the .js.erb file works:

//= depend_on_asset views/template.html

url = '<%= asset_path('views/template.html') %>'

This will recompile this file any time there is a change to views/template.html as desired.

Rails Asset Pipeline: Return digest version when non-digest requested

I think the must elegant way is doing some Controller to do some redirect 302 to you assets.

You can paste to your client a code link /public-assets/my_assets

In your route create the route :

match '/public-assets/:asset_name' => 'PublicAsset#index'

And create your controller PublicAssetController

class PublicAssetContoller < ApplicationController::Base

def index
redirect_to asset_path(params[:asset_name])
end

end

Rails not using digested assets in production

You may need to run the precompile task on production after deployment.

I am under assumption that Heroku does this by default.

There are a few examples found here:

https://gist.github.com/fancyremarker/9652688



Related Topics



Leave a reply



Submit