要討論Webpack 2中新增的這兩個plugin的功能疲吸,還要先從使用Webpack打包的項目的前端資源緩存方案說起弄唧。
通常在使用了Webpack的項目中我們會使用CommonsChunkPlugin來將所有依賴的第三方包打包到一個名為vender的chunk中咧虎。與此同時河狐,為了避免每次更改項目代碼時導致venderchunk的chunkHash改變淑趾,我們還會單獨生成一個manifestchunk絮记。
舉個例子振乏,假設我們有一個項目恰聘,項目中入口文件為index.js戳气。其內容如下:
importaddfrom'./src/add';importleftPadfrom'left-pad';importjsonpfrom'jsonp';add(1,2);
通常我們的webpack.config.js文件就會有類似如下的配置:
constpath =require('path');constwebpack =require('webpack');module.exports = {entry: {'app':'./index.js','vender': ['left-pad','jsonp']? },output: {filename:'[name].[chunkHash].js',path: path.resolve(__dirname,'build')? },resolve: {extensions: ['.js']? ? },module: {? ? ? ? ...? ? },plugins:[newwebpack.optimize.CommonsChunkPlugin({name: ['vender','manifest'],minChunks:Infinity,? ? ? ? })? ]};
這時链患,通過Webpack打包,會生成三個文件:
假設我們修改了./src/add.js文件瓶您,重新打包麻捻,會得到:
可以看到只有app和manifest這兩個chunk的chunkHash改變了纲仍,而vender的chunkHash和之前保持了一致。這就使得vender可以被緩存在客戶端贸毕,從而減少客戶端的下載量郑叠。
但如果是新添加一個文件呢?
假設我們在項目中新加了一個文件./src/add2.js明棍。此時index.js的內容如下:
importaddfrom'./src/add';importadd2from'./src/add2';importleftPadfrom'left-pad';importjsonpfrom'jsonp';add(1,2);add2(1);
此時再次構建乡革,會得到如下的輸出:
這就和我們期望的行為不一致了,因為我們并沒有修改依賴的第三方包摊腋,但是venderchunk的chunkHash也發(fā)生了更改沸版。
導致這個結果的原因在于,由于引入了一個新模塊兴蒸,使得打包過程中部分模塊的模塊ID發(fā)生了改變视粮。而模塊ID的改變,直接導致了包含這些模塊的chunk內容改變类咧,進而導致chunkHash的改變馒铃。
注意看下圖:
藍色框中的模塊ID為3的模塊就是我們新加的模塊。由于它被插在了ID為3的位置痕惋,導致后續(xù)所有模塊的ID都發(fā)生了更改区宇。
既然找到了問題的原因,那么解決方案也就很明了了值戳。那就是找到一種和順序無關的模塊ID命名方式议谷。最容易想到的就是基于文件名或者文件內容的哈希值這兩種方案了。其實也就是今天要說的NamedModulesPlugin與HashedModuleIdsPlugin的功能堕虹。
比如卧晓,我們在項目中啟用HashedModuleIdsPlugin:
plugins:[newwebpack.optimize.CommonsChunkPlugin({name: ['vender','manifest'],minChunks:Infinity,? ? ? ? }),newwebpack.HashedModuleIdsPlugin()? ]
此時,再次構建項目得到:
可以看到各個模塊的ID已經(jīng)變成一小段哈希值赴捞。這時逼裆,在項目中添加./src/add2.js。重新構建赦政,得到輸出:
可以看出胜宇,兩次構建之間,venderchunk的chunkhash以及各模塊的模塊ID都保持了一致恢着。從而達到了最佳的緩存效果桐愉。
使用NamedModulesPlugin效果類似,此處不再演示掰派。本文涉及的所有代碼都可以在github上找到从诲。