1. 程式人生 > >webpack.optimize.CommonsChunkPulgin is not a constructor???請看CommonsChunkPlugin VS SplitChunksPlugin

webpack.optimize.CommonsChunkPulgin is not a constructor???請看CommonsChunkPlugin VS SplitChunksPlugin

 webpack團隊人員臥薪嚐膽五個多月的時間終於帶來的webpack4+,個人覺得webpack4帶來的最大優化便是對於懶載入塊拆分的優化,刪除了CommonsChunkPlugin,新增了優化後的SplitChunksPlugin,那麼CommonsChunkPlugin的痛點在哪?SplitChunksPlugin的優化又是在哪?

1、CommonsChunkPlugin的痛

記得17年始,我剛開始用webpack搭建一個vue的單頁應用框架時,我陸續的丟擲了幾個問題:

1、如何避免單頁應用首次的入口檔案過大?

這個問題處理起來倒簡單,webpack支援import()語法實現模組的懶載入,可以做到隨用隨載,也就是除了首頁要用到檔案,其他模組使用懶載入就能有效的避免入口檔案過大

2、入口模組以及剩下的懶載入模組引用公用的模組時,程式碼會重複嗎?webpack會處理嗎?怎麼處理?

程式碼重複是肯定的,如果父級模組中沒有引入懶載入模組的共用模組,那麼懶載入各模組間就會出現程式碼重複;webpack能處理,那麼怎麼處理呢?這時CommonsChunkPlugin就信誓旦旦地登場了,它能夠將全部的懶載入模組引入的共用模組統一抽取出來,形成一個新的common塊,這樣就避免了懶載入模組間的程式碼重複了,哇!好強大,點個贊。可惜的是,又回到了第一個問題,你把共用的東西都抽出來了,這樣又造成了入口檔案過大了。以下是CommonsChunkPlugin時代常用的配置

new webpack.optimize.CommonsChunkPlugin({
  name: 'vendor',
  // 引入node_modules的依賴全抽出來
  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
    )
  }
  // 或者直接minChunks: 2,重複模組大於2的全部抽出來
}),
總之你在程式碼重複與入口檔案控制方面你得做個平衡,而這個平衡挺不利於多人開發的,也不易於優化.

CommonsChunkPlugin的痛,痛在只能統一抽取模組到父模組,造成父模組過大,不易於優化

2、SplitChunksPlugin的好

前面講了那麼多,其實SplitChunksPlugin的登場就是為了抹平之前CommonsChunkPlugin的痛的,它能夠抽出懶載入模組之間的公共模組,並且不會抽到父級,而是會與首次用到的懶載入模組並行載入,這樣我們就可以放心的使用懶載入模組了,以下是官網說明的一些例子:

假設存在以下chunk-a~chunk-d

chunk-a: react, react-dom, some components

chunk-b: react, react-dom, some other components

chunk-c: angular, some components

chunk-d: angular, some other components

webpack會自動建立兩個chunk模組,結果如下:

chunk-a~chunk-b: react, react-dom

chunk-c~chunk-d: angular

chunk-a to chunk-d: Only the components

SplitChunksPlugin使用官網預設配置基本可以滿足大多數單頁應用了

module.exports = {
  //...
  optimization: {
    splitChunks: {
      chunks: 'async',
      minSize: 30000,
      minChunks: 1,
      maxAsyncRequests: 5,
      maxInitialRequests: 3,
      automaticNameDelimiter: '~',
      name: true,
      cacheGroups: {
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10
        },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true
        }
      }
    }
  }
};

以下是我對於多頁應用補充的配置

optimization: {
    splitChunks: {
      // 抽離入口檔案公共模組為commmons模組
      cacheGroups: {
        commons: {
          name: "commons",
          chunks: "initial",
          minChunks: 2
        }
      }
    }
  },

SplitChunksPlugin的好,好在解決了入口檔案過大的問題還能有效自動化的解決懶載入模組之間的程式碼重複問題