Issue 1:
Feature request

What is the expected behavior?

The documentation says that

The [contenthash] substitution will add a unique hash based on the content of an asset. When the asset's content changes, [contenthash] will change as well.

However, the [contenthash] does not actually match the hash of the file, i.e. the result you would get if you ran md5sum or sha256sum on the file.

This StackOverflow answer explains why: the [contenthash] is computed before minification.

The feature request is to compute the [contenthash] after minification/any other post-processing steps, or at least provide an option to do so.

What is motivation or use case for adding/changing the behavior?

This would have nice properties, such as allowing proxies to validate the integrity of a file just by comparing its hash to the filename.

How should this be implemented in your opinion?

Change the point in the process where the [contenthash] is computed. I don't know anything about webpack's architecture so I have no idea how hard this is.

Are you willing to work on this yourself?

I'm not a webpack developer but if there was some guidance from an expert I could take a stab at it.

Issue 2:
Feature request

Please natively support output chunk hashing that is based on chunks output rather than their input (i.e., output.filename = "[name]-[chunkhash].js").

Why? you may ask? Because hashing is mainly used for production asset caching. Right now, there are at least three ways the content of a chunk can change, and only one of those causes the [chunkhash] value to change.

When you deploy a new version of your code, you want browsers not to use old, stale assets. In theory, hashes should be based on the content of the files, such that when the files changes, the hash changes, and you can leverage the asset manifest to write out a new <script> or <link> tag with the new hash. And obviously, the advantage of [chunkhash] vs [hash] is that if you make a change that only changes a single chunk, you do not "invalidate" the cache of unchanged chunks, thus improving the performance for end users who have already downloaded unchanged chunks.

Going back to those three ways a chunk's content can change:

You make a change to your entrypoint or its dependencies.

You make a change to the webpack config (e.g. adding/removing/changing a plugin/loader).

You upgrade a loader/plugin version.

Right now, only 1 is supported, which leaves a pretty glaring hole. You may, say, add source maps (2) only to discover that your CDN is still serving a stale version of your code without source maps because the [chunkhash] was not updated.

It seems like tools like https://github.com/erm0l0v/webpack-md5-hash may address this, but this seems like a pretty huge flaw in the expected behavior out-of-the-box.

What is the expected behavior?

The expected behavior is that when the content of a chunk changes, the hash for that chunk should change too.

What is motivation or use case for adding/changing the behavior?

As explained above, the motivation is the principle of least surprise. Right now, it's surprising that changing configuration, which may have profound effects on the output, silently slips by as an output asset with the same name as a stale version of the asset.

How should this be implemented in your opinion?

I think there are a few options:

Reimplement [chunkhash], though I seem to remember reading issues about challenges with sourcemaps.

Implement a new token value (e.g. output.filename = "[name]-[chunkhash]-[webpackhash].js") such that changing anything about your webpack config or its dependencies allows you to bust the cache.

Other Considerations

To hack around this in the mean time, I've employed a custom hashing function that uses the final JSONified value of the webpack config as hash salt:

// webpack.config.js
const config = {};

class Hasher {
constructor() {
const hash = require("crypto").createHash("sha256");
hash.update(JSON.stringify(config));
return hash;
}
}

Object.assign(config, {
output: {
filename: isProd ? "[name]-[chunkhash].js" : "[name].js",
hashFunction: Hasher
},
...
})

module.exports = config;

This creates a custom hashing function that injects a JSONified version of the webpack config such that changes to webpack's configuration cause the hash to change. In theory, we could use output.hashSalt, but that cannot be lazily evaluated once the entire webpack config has been constructed. Furthermore, output.hashSalt does not get used for MiniCssExtractPlugin's [contenthash], but (confusingly) output.hashFunction does. Finally, this only accounts for changes in the webpack config itself—it does not account for underlying changes in plugins/loaders due to, e.g., version upgrades.

Are you willing to work on this yourself?

Yes! But I think I need help.