In Nanoc, routing strictly happens before compilation. This prevents an output filename from depending on the compiled content.
This is limiting particularly for stylesheet fingerprinting. Ideally, each stylesheet contains the hash of its own compiled content in the filename, but Nanoc is only able to calculate a hash from the raw, uncompiled input.
As an example, here is how the nanoc.ws web site handles fingerprinting for stylesheets:
compile '/assets/style/*' do filter :sass, syntax: :scss write item.identifier.without_ext + '-' + fingerprint('/assets/style/*') + '.css' end
def fingerprint(pattern) contents = @items.find_all(pattern).map do |i| i.binary? ? File.read(i[:filename]) : i.raw_content end Digest::SHA1.hexdigest(contents.join(''))[0..15] end
The implementation of
#fingerprint looks icky, but there is a bigger issue.
If multiple stylesheets exist (e.g.
/assets/style/print.scss), their filenames will depend on all partials and all non-partials in the
/assets/style directory, which might cause a stylesheet’s fingerprint to change even though their contents haven’t changed.
For each item, Nanoc runs several outdatedness rules, which determine whether or not the item is outdated and thus needs to be recompiled. These outdatedness rules answer questions such as these:
If none of these outdatedness rules respond with “yes,” the item is not considered to be outdated, and will not be recompiled.
The last mentioned outdatedness rule in the list above is of interest: if the corresponding output file does not exist, Nanoc will consider the item as outdated, and compile it.
This is why Nanoc needs to know the file path before compiling the item.
A dependency-querying API would help for generating fingerprints that are taken from only the necessary items. In the stylesheet fingerprinting example above, the
fingerprint(glob) call would become
@items.find_all(pattern) would become something like
Such a dependency-querying API wouldn’t solve the underlying problem of not being able to generate a fingerprint from the compiled content, however.
To do: Probably solvable if Nanoc uses an internal output databases that relies on item identifiers (or arbitrarily-assigned UUIDs) rather than paths. CoW would then help with reducing filesystem usage.
GitHub. “Cache Fingerprinting Doesn’t Take Account of Change to Non-Partial · Issue #251 · nanoc/nanoc.ws.” Accessed January 12, 2021. https://github.com/nanoc/nanoc.ws/issues/251.