最近讀了一下webpack的文檔,讀到CommonsChunkPlugin這個插件,深深折服於webpack的強大,同時也產生了一些本身的疑問。javascript
首先,CommonsChunkPlugin這個插件是用來提取公共代碼的,經過將公共模塊提取出來,只在頁面加載的時候引入一次,提高應用的加載效率。java
順便提一下,chunk其實就是代碼塊的意思,多是一個或多個模塊,通常提取後就是一個js文件。node
CommonsChunkPlugin有中文翻譯的文檔,可是感受並非很通順,英文文檔看完也有一些疑惑,好比minChunks究竟是作什麼用的,怎麼用?chunks是什麼?webpack
首先貼一下文檔。web
{ name: "string", names: "string[]", filename: "string", minChunks: "number|Infinity|function(module, count) -> boolean", chunks: "string[]", children: "boolean", async: "boolean|string", minSize: "number" }
entry
中定義,該chunk會被直接提取;若是沒有定義,則生成一個空的chunk來提取其餘全部chunk的公共代碼。output
配置項中文件名的佔位符。未定義時使用name
做爲文件名。entry
中定義的入口chunk。minChunks:在一個模塊被提取到公共chunk以前,它必須被最少minChunks
個chunk所包含(通俗的說就是一個模塊至少要被minChunks
個模塊所引用,才能被提取到公共模塊。)。minChunks參數有三點須要說明:緩存
Infinity
,則建立一個公共chunk,可是不包含任何模塊,內部是一些webpack生成的runtime代碼和chunk自身包含的模塊(若是chunk存在的話)。options.name
的子塊和options.chunks
的兄弟塊被建立。該chunk會與options.chunks
並行加載。你也可使用該參數指定輸出的文件名。咱們看一個簡單的例子。app
module.exports = { entry: { app: './src/index.js', vender: [ 'lodash', 'otherlib' ] }, plugins: [ new webpack.optimize.CommonsChunkPlugin({ name: 'vender' }) ], output: { // 使用Hash來命名文件,實現文件緩存的功能。當文件內容發生變化,文件名會隨之改變。 filename: '[name].[chunkhash].js', path: path.resolve(__dirname, 'dist') } };
上面的代碼中定義了兩個入口,app和vender(公共庫),plugins中使用CommonsChunkPlugin提取vender。異步
vender是咱們提取出來的公共chunk,一般不會被修改,因此理應在每次編譯後文件名保持一致。然而,咱們嘗試修改入口文件index.js會發現,vender的文件名會發生變化。async
緣由呢上面提到過,因爲每次編譯會致使vender的module.id發生變化,內部的runtime代碼隨之發生改變。ide
解決方案有如下幾種:
module.exports = { entry: { app: './src/index.js', vender: [ 'lodash' ] }, plugins: [ new webpack.optimize.CommonsChunkPlugin({ name: 'vender', minChunks: Infinity }), new webpack.optimize.CommonsChunkPlugin({ name: 'manifest', chunks: ['vender'] }) ], output: { filename: '[name].[chunkhash].js', path: path.resolve(__dirname, 'dist') } };
代碼中再次使用了CommonsChunkPlugin,從vender中提取出了名爲manifest的運行時代碼。
Vue在production模式中使用以下配置
// split vendor js into its own file new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', minChunks: function (module, count) { // any required modules inside node_modules are extracted to vendor return ( module.resource && /\.js$/.test(module.resource) && module.resource.indexOf( path.join(__dirname, '../node_modules') ) === 0 ) } }), // extract webpack runtime and module manifest to its own file in order to // prevent vendor hash from being updated whenever app bundle is updated new webpack.optimize.CommonsChunkPlugin({ name: 'manifest', chunks: ['vendor'] })
minChunks配置項有兩個參數,module爲當前要提取的源chunk中所包含的模塊,count表示模塊的個數。
自定義函數會被循環調用,直到遍歷完全部模塊。
module.resource爲模塊的絕對路徑,因此這段代碼判斷了模塊是否在node_modules下,是的話則打包到vender中。
後面一個CommonsChunkPlugin從vender中提取了運行時代碼,避免每次打包vender的Hash值都發生變化致使緩存無效。
若有問題,歡迎指正。