webpack中的hash、chunkhash、contenthash區別

wind4gis發表於2017-12-29

參考:medium.com/@okonetchni…

hash、chunkhash、contenthash

  hash一般是結合CDN快取來使用,通過webpack構建之後,生成對應檔名自動帶上對應的MD5值。如果檔案內容改變的話,那麼對應檔案雜湊值也會改變,對應的HTML引用的URL地址也會改變,觸發CDN伺服器從源伺服器上拉取對應資料,進而更新本地快取。但是在實際使用的時候,這幾種hash計算還是有一定區別。

我們先建一個測試案例來模擬下:

  • 專案結構

    我們的專案結構很簡單,入口檔案index.js,引用了index.css。然後新建了jquery.js和test.js作為公共庫。

      //index.js
    
      require('./index.css')
      module.exports = function(){
      	console.log(`I'm jack`)
      	var a = 12
      }
    
    
      //index.css
    
      .selected : {
          display: flex;
          transition: all .6s;
          user-select: none;
          background: linear-gradient(to bottom, white, black);
      }
    複製程式碼

接著我們修改webpack.config.js來模擬不同hash計算

  • hash

    hash是跟整個專案的構建相關,只要專案裡有檔案更改,整個專案構建的hash值都會更改,並且全部檔案都共用相同的hash值

      var extractTextPlugin = require('extract-text-webpack-plugin'),
      	path = require('path')
      
      module.exports = {
      	context : path.join(__dirname,'src'),
      	entry:{
      		main: './index.js',
      		vender:['./jquery.js','./test.js']
      	},
      	module:{
      		rules:[{
      			test:/\.css$/,
      			use: extractTextPlugin.extract({
      				fallback:'style-loader',
      				use:'css-loader'
      			})
      		}]
      	},
      	output:{
      		path:path.join(__dirname, '/dist/js'),
      		filename: 'bundle.[name].[hash].js',
      	},
      	plugins:[
      		new extractTextPlugin('../css/bundle.[name].[hash].css')
      	]
      }
    複製程式碼

    根據上面的配置,我們執行webpack命令之後,可以得到下面的結果

    採用hash計算的執行結果1:

webpack中的hash、chunkhash、contenthash區別

執行結果2:
複製程式碼

webpack中的hash、chunkhash、contenthash區別

我們可以看到構建生成的檔案hash值都是一樣的,所以hash計算是跟整個專案的構建相關,同一次構建過程中生成的雜湊都是一樣的
複製程式碼
  • chunkhash

    採用hash計算的話,每一次構建後生成的雜湊值都不一樣,即使檔案內容壓根沒有改變。這樣子是沒辦法實現快取效果,我們需要換另一種雜湊值計算方式,即chunkhash。

    chunkhash和hash不一樣,它根據不同的入口檔案(Entry)進行依賴檔案解析、構建對應的chunk,生成對應的雜湊值。我們在生產環境裡把一些公共庫和程式入口檔案區分開,單獨打包構建,接著我們採用chunkhash的方式生成雜湊值,那麼只要我們不改動公共庫的程式碼,就可以保證其雜湊值不會受影響。

      var extractTextPlugin = require('extract-text-webpack-plugin'),
      	path = require('path')
      
      module.exports = {
      	...
      	...
      	output:{
      		path:path.join(__dirname, '/dist/js'),
      		filename: 'bundle.[name].[chunkhash].js',
      	},
      	plugins:[
      		new extractTextPlugin('../css/bundle.[name].[chunkhash].css')
      	]
      }
    複製程式碼

    採用chunkhash計算的執行結果1:

webpack中的hash、chunkhash、contenthash區別

執行結果2:
複製程式碼

webpack中的hash、chunkhash、contenthash區別

我們可以看到,由於採用chunkhash,所以專案主入口檔案Index.js及其對應的依賴檔案Index.css由於被打包在同一個模組,所以共用相同的chunkhash,但是公共庫由於是不同的模組,所以有單獨的chunkhash。這樣子就保證了線上上構建的時候只要檔案內容沒有更改就不會重複構建
複製程式碼
  • contenthash

    在chunkhash的例子,我們可以看到由於index.css被index.js引用了,所以共用相同的chunkhash值。但是這樣子有個問題,如果index.js更改了程式碼,css檔案就算內容沒有任何改變,由於是該模組發生了改變,導致css檔案會重複構建。

    這個時候,我們可以使用extra-text-webpack-plugin裡的contenthash值,保證即使css檔案所處的模組裡就算其他檔案內容改變,只要css檔案內容不變,那麼不會重複構建。

      var extractTextPlugin = require('extract-text-webpack-plugin'),
      	path = require('path')
      
      module.exports = {
      	...
      	...
      	output:{
      		path:path.join(__dirname, '/dist/js'),
      		filename: 'bundle.[name].[chunkhash].js',
      	},
      	plugins:[
      		new extractTextPlugin('../css/bundle.[name].[contenthash].css')
      	]
      }
    複製程式碼

    採用contenthash計算的執行結果1:

webpack中的hash、chunkhash、contenthash區別

執行結果2:
複製程式碼

webpack中的hash、chunkhash、contenthash區別

相關文章