tooling.report

feature

Avoiding hashing for a particular resource

Can URL hashing be selectively disabled?

Person in shorts with blue hair walking left

Introduction

Including content hashes in URLs is beneficial for effective caching, however there are certain resources that should not have hashed URLs. Files like robots.txt, index.html and Service Workers can't have hashes in their URLs, because their URLs must always remain the same.

The Test

This test builds multiple resources with configuration to control URL hashing for each. It assesses whether a build tool can selectively hash URLs for specific assets, entry bundles and code-splitted bundles.

hashed-entry.js

import hashedUrl from './hashed-asset.txt';
import unhashedUrl from './unhashed-asset.txt';
console.log(hashedUrl, unhashedUrl);

import('./hashed-chunk.js');
import('./unhashed-chunk.js');

unhashed-entry.js

console.log('Unhashed entry');

hashed-asset.txt

Hashed asset

unhashed-asset.txt

Unhashed asset

hashed-chunk.js

console.log('Hashed chunk');

unhashed-chunk.js

console.log('Unhashed chunk');

Bundling both entries modules should produce 6 files. The 3 files with "hashed" in their names should generate hashed URLs, whereas the 3 files with "unhashed" in their names should generate URLs with no hashes.

Conclusion

browserify

Since separate Gulp tasks can be defined for individual source files, it's possible to separately control the URL hashing for each. In this case index.html is not passed through the hashing task, so its URL is not hashed.

parcel

Parcel does not provide a way to control whether individual resources or bundles recieve hashed URLs. However, it does not include hashes in the URLs of HTML files and Service Workers by default.

Issues

rollup

It is possible to bypass URL hashing in using the the emitFile method, however this requires writing a plugin. This is a non-trivial effort, and it's possible the plugin won't interoperate with other plugins that assume output URLs are hashed.

Rollup also does not support hashing entry bundles conditionally or on a per-bundle basis.

Issues

webpack

The generated filenames for assets handled by file-loader can be configured on a per-file basis by supplying a function for file-loader's name option, which accepts the resource path and returns a filename template to use for generating its output location. The same is true for entry modules, which can have be optionally hashed by supplying a function for output.filename.

In Webpack 4, hashing can't be conditionally applied to code-splitted bundles, because output.chunkFilename does not accept a function. While a custom "chunk name" can be specified in a special comment within import() statements, the filename template where hashing is controlled cannot be customized per-bundle. This has been addressed in Webpack 5, which supports specifying a function for output.chunkFilename just like output.filename. It's worth noting that control over hashing of dependency bundles is the least important of these tests.

Issues