I had a hard time finding a solution here that helped. But this tutorial is great and worked for me.
tl;dr
output: {
filename: '[name].[chunkhash].js'
},
plugins: [
// Order matters. 'vendor' must come before 'runtime'
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor'
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'runtime'
}),
new webpack.NamedModulesPlugin(),
new webpack.NamedChunksPlugin()
]
You MUST:
- Use
chunkhash
(nothash
) in your output filename - Hash is the hash of the entire bundle, so it will be the same for every chunk (which is not what we want since we want to cache our chunks separately). (link) - Extract
runtime
viaCommonsChunkPlugin
- This "runtime" chunk includes the webpack manifests and so will change anytime any of your chunk hashes change. If this is included in one of your chunks, it will cause that entire chunk to be invalidated any time one of your other chunk hashes change. (link) - Use
NamedModulesPlugin
- By default, webpack uses sequential IDs to identify modules. Because of this, adding a new module to one chunk can cause the contents of the others to change. This plugin changes this behavior to use the path to the module rather than a numerical ID to identify a module. (link) - Use
NamedChunksPlugin
- Similar toNamedModulesPlugin
, but for chunks. Prevents hashes from changing when the order of your chunks changes for some reason. (link)
NOTE: Despite the recommendation in the caching guide to use HashedModuleIdsPlugin
in production, NamedModulesPlugin
actually leads to smaller bundle sizes if you are gzipping your project. Props to @timse for discovering this.