What is the purpose of webpack [hash] and [chunkhash]?
Could somebody tell me what is the the purpose [hash] and [chunkhash] and where do they come from?
output: {
path: "/home/proj/cdn/assets/[hash]",
publicPath: "http://cdn.example.com/assets/[hash]/"
}
This one wasn't obvious for me for a while, so I think it deserves some more detailed explanation.
What the official documentation says:
A brief description from the official documentation about their purpose:
A simple way to ensure the browser picks up changed files is by using
output.filename
substitutions. The[hash]
substitution can be used to include a build-specific hash in the filename, however it's even better to use the[contenthash]
substitution which is the hash of the content of a file, which is different for each asset.
Another explanation one by one from the documentation of output.filename
:
-
[hash]
is a "unique hash generated for every build" -
[chunkhash]
is "based on each chunks' content" -
[contenthash]
is "generated for extracted content"
Let's make it more more understandable with examples:
I have 3 files in my src
directory: index.js
, index.css
, vendors.js
Relevant parts from my example Webpack config:
(not a full, working config!)
entry: {
index: ["./src/index.js", "./src/index.css"],
vendors: ["./src/vendors.js"]
},
output: {
filename: "[name].[hash].js"
}
plugins: [
new MiniCssExtractPlugin({
filename: "[name].[hash].css"
})
]
So I have 2 chunks name, index
and vendors
, but look that the index
chunk will also have css
content because it imports a css
file in the array. When building, the css
part will be exported to a separate file using MiniCssExtractPlugin
(in my case) but Webpack knows that index.js
and index.css
belong to the same chunk.
Now let's try to build it with different hashing types. (changing the two filename
option equally)
Using [hash]:
Every file has the same hash, because [hash]
is generated based on all of our used source files. If I re-run the build without changing anything, the generated hash will remain the same. If I edit only one file then hash will change and all my generated bundles will have this new hash in their name.
Using [chunkhash]:
As you see, the 1st and 2nd files were coming from the same index
chunk, so they have the same hash in their name. It's because [chunkhash]
is generated based on the whole content of the given chunk. So if I edit let's say index.css
and re-build, the files coming from the index
chunk will have a new hash, but the one from vendors
chunk will remain the same as was before.
Using [contenthash]:
This one is obvious. Each generated file has got a unique hash in their name, calculated from the content of that file. If I change let's say index.css
an re-build, only the generated index.css
will have a new hash.
Basically its related to browser cacheing - when you serve assets you generally want to tell the client/browser that they can use the same script/stylesheet/jpeg etc without having to download it every single time. This is done by sending the appropriate HTTP header fields.
The problem then is how long should you tell the client they can keep using the same stylesheet for example? If you redesign your site and they dont download your new stylesheet they wont see those changes. The solution is usually to add some kind of identifier or version number to the stylesheet file name - if this id/version changes when the stylesheet changes (and thus the file name is different) the browser will download it again (this is known as cache busting).
Basically webpack can add a hash to the bundle output name that, being a function of the bundle content, will be different when the content changes - thus automating the process. chunkhash
does the same thing if you are splitting a bundle into multiple chunks.
Heres some non-webpack related discussion: Strategies for Cache-Busting CSS