hash是通過既定的數(shù)據(jù)摘要算法(目前使用最廣泛的是md5)計(jì)算出來的hash值右锨。
webpack內(nèi)置的hash相關(guān)的配置有兩個(gè):hash和chunkhash。
名稱 | webapck 1 | webapck 2及以上 |
---|---|---|
hash | The hash of compilation | The hash of module identifier |
chunkhash | The hash of the chunk | The hash of the chunk content |
webpack的compilation對象代表某個(gè)版本的資源對應(yīng)的編譯進(jìn)程曲秉。當(dāng)使用webpack的development中間件時(shí)钱床,每次檢測到項(xiàng)目文件有改動(dòng)就會(huì)創(chuàng)建一個(gè)新的compilation观堂,進(jìn)而能夠針對改動(dòng)產(chǎn)生全新的編譯文件督赤。compilation對象包含當(dāng)前模塊資源、待編譯文件拴清、有改動(dòng)的文件和監(jiān)聽依賴的所有信息靶病。
注:與compilation對應(yīng)的有個(gè)compiler對象,通過對比贷掖,可以幫助大家對compilation有更深入的理解嫡秕。compiler對象代表的是配置完備的Webpack環(huán)境。 compiler對象只在Webpack啟動(dòng)時(shí)構(gòu)建一次苹威,由Webpack組合所有的配置項(xiàng)構(gòu)建生成昆咽。compiler對象代表的是不變的webpack環(huán)境,是webpack本身,而compilation對象針對的是隨時(shí)可變的項(xiàng)目文件掷酗,只要文件有改動(dòng)调违,compilation就會(huì)被重新創(chuàng)建。
-
hash
對于hash的理解泻轰,我認(rèn)為webpack 1中的The hash of compilation定義更準(zhǔn)確技肩,可以理解成是項(xiàng)目總體文件的hash值。所以若打包文件輸出時(shí)以hash命名浮声,項(xiàng)目中任何一個(gè)文件修改構(gòu)建后都會(huì)生成新的hash,會(huì)影響所有資源的緩存虚婿。比如webpack配置如下:
output: {
filename: '[name].[hash:8].js'
}
-
chunkhash
chunk在webpack中的含義可以理解成多個(gè)模塊合并成的一個(gè)"新模塊",依據(jù)其自身的代碼內(nèi)容根據(jù)一定的摘要算法所得的hash值泳挥。也就是特定模塊獨(dú)有的hash值然痊。webpack配置更改如下:
output: {
filename: '[name].[chunkhash:8].js'
}
此時(shí)編譯后輸出的文件名中的hash值將不再一樣。
-
contenthash
contenthash并不是webpack的另外一中hash屉符,而是由ExtractTextPlugin插件(主要作用: 將css代碼從打包后的js代碼中分離出來)提供的剧浸,代表被導(dǎo)出的css部分代碼內(nèi)容計(jì)算后的的hash值
1. 在webpack構(gòu)建過程中,我們可以狹隘的認(rèn)為他只認(rèn)js文件矗钟,其他文件都需要借助js文件構(gòu)建唆香,比如css資源必須都在js中引入。例如在main.js文件中引入main.css文件:
import 'main.css';
2. webpack默認(rèn)將構(gòu)建后的css代碼合并到引用它的js文件中吨艇。那么css是怎么引入到頁面中的呢躬它?
----其實(shí)就是js在運(yùn)行的時(shí)候動(dòng)態(tài)創(chuàng)建style標(biāo)簽,然后append進(jìn)head中的东涡。所以在本地開發(fā)中若是沒有開啟ExtractTextPlugin的話虑凛,那么css代碼都是內(nèi)聯(lián)在html中的。
3. 盡然chunkhash已經(jīng)能以一個(gè)文件為單位去生成一個(gè)特定的chunkhash了那软啼,那么為什么還要用contenthash呢?
大家考慮怎么一個(gè)場景:
----假設(shè)有主模塊main.js, 同步模塊sync.js延柠,其中mian.js中引入了main.css, 將這三個(gè)模塊按下面代碼的配置進(jìn)行構(gòu)建打包到“同一個(gè)文件”(此時(shí)配置了ExtractTextPlugin插件祸挪,css代碼會(huì)單獨(dú)抽離到一個(gè)文件,若不添加ExtractTextPlugin會(huì)被打包到一個(gè)js文件)
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
filename: './dist/[name].[chunkhash:8].css',
use: [
'css-loader',
'postcss-loader',
],
}),
}
構(gòu)建后會(huì)輸出main.8a132fcd.js和main.8a132fcd.css兩個(gè)文件贞间,二者的chunkname和hash會(huì)是一樣的贿条;
① 若后續(xù)我們修改了main.js或是sync.js里面的代碼,重新構(gòu)建后劳闹,會(huì)生成新的chunkhash,那么構(gòu)建后的js文件和css文件的hash都會(huì)改變债沮。
② 若是我們值修改了main.css代碼的話错森,重新構(gòu)建后,會(huì)發(fā)現(xiàn)chunkhash并未改變公黑,這是為什么?
-----這是因?yàn)閷?dǎo)入ExtractTextPlugin后會(huì)將css代碼獨(dú)立導(dǎo)出,它的修改不會(huì)引起主js文件chunkhash的改變凡蚜,sync.js人断、mian.js、main.css三個(gè)文件本屬于同一個(gè)chunk,被導(dǎo)出的css雖然不會(huì)參與chunkhash的計(jì)算朝蜘,但是也不會(huì)做為一個(gè)獨(dú)立的chunk計(jì)算恶迈,所以name和hash還是取主js文件的。
這樣就會(huì)有一個(gè)問題谱醇,要是css改變了的話暇仲,重新構(gòu)建后的css文件名并沒有改變會(huì)導(dǎo)致用戶瀏覽器還是會(huì)拉取緩存中的資源,所以最好還是配置成如下的contenthash
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
filename: './dist/[name].[contenthash:8].css',
use: [
'css-loader',
'postcss-loader',
],
}),
}
這樣改后修改main.js或者sync.js,css文件的hash不會(huì)變副渴,若單獨(dú)修改css奈附,那么主js文件的hash也不會(huì)改變