hash是通過既定的數據摘要算法(目前使用最廣泛的是md5)計算出來的hash值。
webpack內置的hash相關的配置有兩個: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對象代表某個版本的資源對應的編譯進程。當使用webpack的development中間件時,每次檢測到項目文件有改動就會創建一個新的compilation,進而能夠針對改動產生全新的編譯文件。compilation對象包含當前模塊資源、待編譯文件、有改動的文件和監聽依賴的所有信息。
注:與compilation對應的有個compiler對象,通過對比,可以幫助大家對compilation有更深入的理解。compiler對象代表的是配置完備的Webpack環境。 compiler對象只在Webpack啟動時構建一次,由Webpack組合所有的配置項構建生成。compiler對象代表的是不變的webpack環境,是webpack本身,而compilation對象針對的是隨時可變的項目文件,只要文件有改動,compilation就會被重新創建。
-
hash
對于hash的理解,我認為webpack 1中的The hash of compilation定義更準確,可以理解成是項目總體文件的hash值。所以若打包文件輸出時以hash命名,項目中任何一個文件修改構建后都會生成新的hash,會影響所有資源的緩存。比如webpack配置如下:
output: {
filename: '[name].[hash:8].js'
}
-
chunkhash
chunk在webpack中的含義可以理解成多個模塊合并成的一個"新模塊",依據其自身的代碼內容根據一定的摘要算法所得的hash值。也就是特定模塊獨有的hash值。webpack配置更改如下:
output: {
filename: '[name].[chunkhash:8].js'
}
此時編譯后輸出的文件名中的hash值將不再一樣。
-
contenthash
contenthash并不是webpack的另外一中hash,而是由ExtractTextPlugin插件(主要作用: 將css代碼從打包后的js代碼中分離出來)提供的,代表被導出的css部分代碼內容計算后的的hash值
1. 在webpack構建過程中,我們可以狹隘的認為他只認js文件,其他文件都需要借助js文件構建,比如css資源必須都在js中引入。例如在main.js文件中引入main.css文件:
import 'main.css';
2. webpack默認將構建后的css代碼合并到引用它的js文件中。那么css是怎么引入到頁面中的呢?
----其實就是js在運行的時候動態創建style標簽,然后append進head中的。所以在本地開發中若是沒有開啟ExtractTextPlugin的話,那么css代碼都是內聯在html中的。
3. 盡然chunkhash已經能以一個文件為單位去生成一個特定的chunkhash了那,那么為什么還要用contenthash呢?
大家考慮怎么一個場景:
----假設有主模塊main.js, 同步模塊sync.js,其中mian.js中引入了main.css, 將這三個模塊按下面代碼的配置進行構建打包到“同一個文件”(此時配置了ExtractTextPlugin插件,css代碼會單獨抽離到一個文件,若不添加ExtractTextPlugin會被打包到一個js文件)
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
filename: './dist/[name].[chunkhash:8].css',
use: [
'css-loader',
'postcss-loader',
],
}),
}
構建后會輸出main.8a132fcd.js和main.8a132fcd.css兩個文件,二者的chunkname和hash會是一樣的;
① 若后續我們修改了main.js或是sync.js里面的代碼,重新構建后,會生成新的chunkhash,那么構建后的js文件和css文件的hash都會改變。
② 若是我們值修改了main.css代碼的話,重新構建后,會發現chunkhash并未改變,這是為什么?
-----這是因為導入ExtractTextPlugin后會將css代碼獨立導出,它的修改不會引起主js文件chunkhash的改變,sync.js、mian.js、main.css三個文件本屬于同一個chunk,被導出的css雖然不會參與chunkhash的計算,但是也不會做為一個獨立的chunk計算,所以name和hash還是取主js文件的。
這樣就會有一個問題,要是css改變了的話,重新構建后的css文件名并沒有改變會導致用戶瀏覽器還是會拉取緩存中的資源,所以最好還是配置成如下的contenthash
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
filename: './dist/[name].[contenthash:8].css',
use: [
'css-loader',
'postcss-loader',
],
}),
}
這樣改后修改main.js或者sync.js,css文件的hash不會變,若單獨修改css,那么主js文件的hash也不會改變