1

How to implement cache busting with Nanoc?

For instance, add MD5 checksums to all image/font/js/etc resource links on HTML and CSS files. For instance, if I had index.html and images/badger.jpg, I'd like the image link on the page to be changed to something like

`href="images/badger.jpg?12345"`

assuming that 12345 would be the correct MD5 hash of badger.jpg.

raimohanska
  • 3,265
  • 17
  • 28

2 Answers2

2

You could go for a routing approach. I recommend to use actually different filenames instead of a querystring - some http caches won't cache urls with querystring.

route '/stylesheet/' do
  csum = [File.open(item[:filename]).read.checksum]
  # add other files you include from your stylesheet.less (if you use less)
  csum += Dir['content/styles/*'].select { |i| File.file?(i) }.map { |f| File.read(f).checksum }
  '/style-' + csum.checksum + '.css'
end

route '*' do
  ext = item[:extension]
  versionexts = ['css','js']

  if versionexts.include?(ext)
    # versioned filenames, depending on the checksum of the source file
    # these files shouldn't depend on other sources, or you have to checksum them too (see above)
    item.identifier.chop + '-' + File.read(item[:filename]).checksum + '.' + ext
  elsif item.binary?
    # Write item with identifier /foo/ to /foo.ext
    item.identifier.chop + '.' + ext
  else
    # Write item with identifier /foo/ to /foo/index.html
    item.identifier + 'index.html'
  end
end

You can't use the checksum of generated content in routing, as the routing is done before compiling.

Stefan
  • 5,304
  • 2
  • 25
  • 44
  • Now if I have references to my versioned css,js,png files in html,css files, will nanoc grok it and update the references to match these routings? That would be awesome. – raimohanska Jan 25 '13 at 22:12
2

Arjan van der Gaag made a gem specifically for this: https://github.com/avdgaag/nanoc-cachebuster

To quote the man himself:

Usage is simple, as you only need to install the gem:

$ gem install nanoc-cachebuster 

and require the gem and include the helpers to get going:

# in default.rb
require 'nanoc3/cachebuster' 
include Nanoc3::Helpers::CacheBusting 

You can now use the #fingerprint method in your routing rules:

route '/assets/styles/' do
  item.identifier.chop + fingerprint(item) + '.' + item[:identifier]
end

The gem will make sure that references to files you have fingerprinted will get updated when you compile your site.

Alexander Presber
  • 6,429
  • 2
  • 37
  • 66
iono
  • 2,575
  • 1
  • 28
  • 36