Hash vs ChunkHash vs ContentHash
Webpack 三种哈希策略的区别与使用场景
问题
Webpack 中 hash、chunkhash、contenthash 有什么区别?分别在什么场景使用?
解答
这三种 hash 都用于生成文件名中的哈希值,实现浏览器缓存控制。
hash
整个项目构建的哈希值,所有文件共享同一个 hash。任意文件修改,所有文件的 hash 都会变化。
// webpack.config.js
module.exports = {
output: {
filename: '[name].[hash].js'
}
}
问题:改一个文件,所有文件缓存都失效。
chunkhash
基于 chunk 内容生成的哈希值。同一入口的文件共享一个 chunkhash。
// webpack.config.js
module.exports = {
entry: {
main: './src/index.js',
vendor: './src/vendor.js'
},
output: {
filename: '[name].[chunkhash].js'
}
}
问题:JS 和从中提取的 CSS 共享同一个 chunkhash,改 JS 会导致 CSS 缓存失效。
contenthash
基于文件内容生成的哈希值。只有文件内容变化,hash 才会变。
// webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
output: {
// JS 文件用 chunkhash 或 contenthash
filename: '[name].[contenthash].js'
},
plugins: [
new MiniCssExtractPlugin({
// CSS 文件用 contenthash
filename: '[name].[contenthash].css'
})
]
}
完整配置示例
// webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
entry: {
main: './src/index.js'
},
output: {
// JS 使用 contenthash
filename: '[name].[contenthash:8].js',
// 异步 chunk
chunkFilename: '[name].[contenthash:8].chunk.js'
},
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader']
}
]
},
plugins: [
new MiniCssExtractPlugin({
// CSS 使用 contenthash
filename: '[name].[contenthash:8].css'
})
],
optimization: {
// 将 runtime 代码单独提取,避免影响业务代码 hash
runtimeChunk: 'single',
// 提取公共模块
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
}
}
}
}
}
对比表格
| 类型 | 作用范围 | 变化条件 | 适用场景 |
|---|---|---|---|
| hash | 整个项目 | 任意文件变化 | 开发环境 |
| chunkhash | 同一 chunk | chunk 内容变化 | JS 文件 |
| contenthash | 单个文件 | 文件内容变化 | CSS、图片等资源 |
关键点
hash粒度最粗,整个项目共享,不适合生产环境chunkhash基于入口 chunk,JS 和提取的 CSS 会共享同一个 hashcontenthash粒度最细,只与文件内容相关,缓存利用率最高- 生产环境推荐:JS 用
contenthash,CSS 用contenthash - 配合
runtimeChunk和splitChunks可进一步优化缓存策略
目录