webpack算是個磨人的小妖精了。以前一直站在glup陣營,使用browserify打包,發現webpack已經火到爆炸,深怕被社區遺落,趕忙拿起來把玩一下。原本只想玩一下的。嘗試打包了之後,就想啓個webpack服務器,以後就想添加熱替換,什麼css文件單獨拆分,各類 loader 處理優化打包結果,各類 source-map 有什麼不一樣,一個都不能少。其中添加熱替換時候,由於應用的服務器和webpack服務器沒有使用同一個,產生了一點波折。而後就到了今天這個主題了。
逐步展開今天的主題:
爲何要分離第三方庫?
這個好處顯而易見,第三方庫是比較穩定的,不會輕易改變,利用瀏覽器緩存後,用戶再次加載頁面會減小服務器請求,提升速度優化體驗。提取多個應用(入口)公共模塊的做用和他相似,公共部分會被緩存,全部應用均可以利用緩存內容從而提升性能。
分離第三方庫就能利用瀏覽器換緩存了麼?
一樣顯而易見是否認的,致使沒法利用緩存的因素有不少,好比最明顯的有可能你每次分離的庫文件從新打包都會獲得不一樣的名稱,這個比較容易發現,再好比說後臺的同事給js文件設置的緩存過時時間爲0,這就尷尬了,但0就不能利用緩存了麼?並非,只要文件是徹底不變的,注意是徹底不變,包括修改時間,依然會利用緩存,性能飛起。想利用緩存必須先了解緩存,這裏簡單提一下:
瀏覽器緩存機制是什麼樣的?
HTTP1.1給的策略是使用Cache-control配合Etag,
Cache-control設置舉例:
'Cache-Control': 'public, max-age=600',
max-age即過時時間,若是已過時的話,還會查看Etag,
ETag的值:
Apache中,ETag的值默認是對文件的索引節(INode),大小(Size)和最後修改時間(MTime)進行Hash後獲得的。
若是Etag相同,依然不會請求新資源,而會使用之前的文件。
CommonsChunkPlugin 究竟是用來幹什麼的?
字面理解,提取公共包,公共包那就是不僅一個地方使用嘍,單頁應用(單入口)的庫只有他本身使用,不能算公共包吧?這個插件提取的公共包,每次是會從新打包的(Etag會不一樣),不管是節約打包時間,(雖然微不足道的時間但畢竟是無用功:庫根本沒變麼),仍是對瀏覽器緩存的利用(萬一 max-age 過時了你就放棄緩存了麼?)都不是好的方案。最佳方案浮出水面:DllPlugin
DllPlugin有什麼優點?
只對庫文件打包一次。也就是說,只要庫文件不變,只須要打包一次,之後再打包業務代碼和庫文件不要緊啦,這樣一來真正作到了庫文件永遠是那個庫文件,只要庫文件不變,緩存永遠有效(Etag不變),打起包來把庫丟到腦後,神清氣爽。介紹一下最簡單的使用方式:
首先另寫一個 webpack 配置文件,畢竟是單獨打包庫了,假設 webpack.config.dll.jsjavascript
const path = require('path') const webpack = require('webpack'); module.exports = { entry: { vendor: ['react', 'react-dom', 'react-hot-loader', 'immutable', 'redux', 'react-redux', 'react-router-dom', 'redux-logger', 'redux-persist', 'redux-persist-transform-immutable', 'redux-thunk'], }, output: { filename: 'js/[name].js', path: path.resolve(__dirname, 'public'), library: '[name]', // 當前Dll的全部內容都會存放在這個參數指定變量名的一個全局變量下,注意與DllPlugin的name參數保持一致 }, plugins: [ new webpack.DllPlugin({ path: path.resolve(__dirname, 'public/manifest.json'), // 本Dll文件中各模塊的索引,供DllReferencePlugin讀取使用 name: '[name]', }), ], }
在原來的配置文件中添加 DllReferencePlugin 插件css
new webpack.DllReferencePlugin({ manifest: require('./public/manifest.json'), // 指定manifest.json name: 'vendor', // 當前Dll的全部內容都會存放在這個參數指定變量名的一個全局變量下,注意與DllPlugin的name參數保持一致 }),
終端先運行:
webpack -p --progress --config ./webpack.config.dll.js
把庫文件先打個包,只要庫不變,之後就用這個包了,再打包業務代碼,完活。
推薦策略:
各行其是。
若是是單頁應用,那隻用DllPlugin打包庫文件便可,業務代碼一個包搞定。
若是是多頁應用,DllPlugin打包完庫文件,開發時可能會用不少公共的業務代碼並且可能隨時變更,這就要利用CommonsChunkPlugin來作他本該作的事,再把公共業務提取出來,至於緩存,起碼在頁面間切換時,公共部分仍是會被緩存的。java