Patrick Bougie — web developer / entrepreneur from Montréal, Canada. Founder of WorkSked — a web app to manage employee work schedules and time off.

Rails + Fingerprinting + Sass + Webfonts

The Rails asset pipeline uses fingerprinting, a technique which makes the filename dependent on its contents. Every time a change occurs to an asset file, the filename changes. Fingerprinting is very useful for caching (whether in CDNs, in ISPs or web browsers).

The sass-rails gem provides asset helpers for referencing asset files using the asset pipeline from your sass or scss source code. There is a problem where files are not fingerprinted when a query string or anchor are appended to the filename. This primarily happens when you are using webfonts.

In the following example, the font-url asset helper is referencing files found in /app/assets/fonts. See the scss declaration below:

@font-face {
  font-family: 'open_sans';
  src: font-url('OpenSans-Regular.eot');
  src: font-url('OpenSans-Regular.eot?#iefix') format('embedded-opentype'),
       font-url('OpenSans-Regular.woff') format('woff'),
       font-url('OpenSans-Regular.ttf') format('truetype'),
       font-url('OpenSans-Regular.svg#open_sans') format('svg');
}

The compiled result shows that only some of the assets have fingerprinting embedded in their filename. The assets that have a query string or anchor are not fingerprinted.

@font-face {
  font-family: 'open_sans';
  src: url(/assets/OpenSans-Regular-a73debd18bde171932e62665040438bf.eot);
  src: url(/assets/OpenSans-Regular.eot?#iefix) format("embedded-opentype"),
       url(/assets/OpenSans-Regular-1563ffc1552d93068226f82629b04222.woff) format("woff"),
       url(/assets/OpenSans-Regular-53b7e758ee9be55ca8159e8328fc8ca9.ttf) format("truetype"),
       url(/assets/OpenSans-Regular.svg#open_sans) format("svg");
}

To fix the problem, you have to split the filename from the appended text. Here’s an updated version of the same scss declaration:

@font-face {
  font-family: 'open_sans';
  src: font-url('OpenSans-Regular.eot');
  src: url(font-path('OpenSans-Regular.eot') + '?#iefix') format('embedded-opentype'),
       font-url('OpenSans-Regular.woff') format('woff'),
       font-url('OpenSans-Regular.ttf') format('truetype'),
       url(font-path('OpenSans-Regular.svg') + '#open_sans') format('svg');
}

You may have to restart your Rails server for the changes to compile correctly. Now all your assets are fingerprinted and you can set a far reaching cache expiry date.

Feel free to contact me if you require development services or have any questions / comments.