這三個hash值都是webpack在打包的時候根據內部算法生成的一串字符串,總的來說最大的不同就是其囊括控制的範圍大小不同,對應的控制顆粒度不同。
hash
hash是對webpack整個一次構建而言,在webpack構建中,文件都會帶上對應的MD5值,構建生成的文件hash值都是一樣的。如果出口是hash,那麼一旦針對項目中任何一個文件的修改,都會構建整個項目,重新獲取hash值。如果有目的性的緩存就會失敗。
chunkhash
chunkhash的範圍可以針對某個模塊而言,它會從入口出發,對依賴文件進行解析,構建對應的chunk和hash值。一般的使用是在生產環境對公共庫和程序入口文件單獨抽離開,單獨打包構建,用chunkhash的方式對這些打包後的文件帶上相應hash值。在線上,只要公共庫和入口沒變,其hash值就不會改變,從而達到緩存的目的。
eg:
entry:{
main: path.join(__dirname,'./main.js'),
vendor: ['vue']
},
output:{
path:path.join(__dirname,'./dist'),
publicPath: '/dist/',
filname: 'bundle.[chunkhash].js'
}
此時入口有兩個,main和vendor,此時的打包就會生成main和ventor兩個hash值,這兩個hash值是分別以main和vendor爲入口出髮根據依賴文件構建生成的chunk和hash值。(chunk可以理解爲入口+他依賴的文件構成的模塊)
contenthash
contenthash的範圍更具體和更小,即對某一個文件而言,在webpack中的用法一般是分離js和css,單對css文件來設置。因爲上面的chunkhash存在一個問題:
chunkhash以入口和依賴文件構建的chunk模塊,只要對應其中一個css或則js改變,與其關聯的文件hash值也會改變,但其他內容並沒有改變,一定意義上的緩存也就失效。
比如我js文件邏輯改變了,但是我css樣式並沒有改動,css文件就應該從緩存中加載,不應該從服務器中重新獲取,浪費帶寬和性能。
所以在項目中,通常做法是把項目中css都抽離出對應的css文件來加以引用。
比如使用mini-css-extract-plugin:
const miniCssExtractPlugin=require("mini-css-extract-plugin");
module.exports={
module:{
rules:[
{
test: /\.css$/,
use:[
miniCssExtractPlugin.loader,
'css-loader'
]
}
]
},
plugins:[
new miniExtractPlugin({
filename: 'main.[contenthash:7].css'
})
}
}
main模塊用了chunkhash,這裏單獨把main的css抽離出來用contenhash處理,打包後即使css文件所處的模塊裏就算其他文件內容改變,只要css文件內容不變,那麼就不會重複構建。