Webpack 提取公共代 CommonsChunkPlugin

minhuaF發表於2018-07-03

背景 

如果不提取公共部分會有什麼後果? 

  1. 相同資源重複載入引用,浪費使用者流量以及伺服器成本;

  2. 每個頁面需要載入的資源太多,導致網頁首頁載入緩慢; 

提取之後有什麼優點? 

  1. 相同資源只打包載入一次,減少網路傳輸流量,降低伺服器壓力; 

  2. 頁面載入速度加快,提交使用者體驗; 

具體用法 

思路 

  1. 根據專案使用的技術棧,把所有頁面都要使用到的基礎庫提取出來,形成一個`base.js`,這個檔案包含技術棧執行所需要的所有基礎環境依賴;(只要技術棧不變,基本可以持久快取) 

  2. 剔除所有公共基礎依賴程式碼之後,再從所有頁面中把都依賴的公共程式碼提取出來,形成一個`common.js`; 

  3. 再為每個頁面生成一個獨立的檔案,那這些檔案就不再包含`base.js`、`common.js`的程式碼,只包含各個頁面獨立的業務程式碼; 

Webpack 提取公共代 CommonsChunkPlugin

定義與概念 

CommonsChunkPlugin用於提取公共程式碼,根據配置,把基礎庫以及業務邏輯公共程式碼抽離提取出來,減少資源重複引用; 

CommonsChunkPlugin 對單入口檔案不能提取公共的程式碼,只能提取webpack runtime的環境程式碼;提取的物件是

配置引數

name: ''複製程式碼

提取公共程式碼的檔名

names: string[]複製程式碼

names中配置的是入口名,不是路徑,如果這裡配置的名字與 入口chunk(輸出檔名,在entry中設定或在動態輸出)中的對應起來,則直接提取,如果沒有在entry中同名,則建立一個包含webpack執行環境的環境程式碼,並作為抽離內容,把執行環境從提取入口中抽離出來;

chunks: string[]複製程式碼

chunks 配置的是提取公共程式碼的源,即需要在哪些入口中提取公共的程式碼;我的理解是這裡如果自由配置的話,應該是要在入口chunk那裡選擇需要提取的入口(這個不知道對不對,因為我如果直接引用檔案路徑的話,效果沒看到)

如果不設定這個值,所有入口chunk,都會作為提取的物件

filename: string複製程式碼

common chunk 檔名模版,如果不設定,則不修改原來的檔名(也不會修改在name/names中配置的名字,但是如果配置了,優先使用)

minChunks: number | Infinity | function(module, count) => boolean複製程式碼

number  一個模組被提取之前,必須要在 入口chunks中出現的至少次數;

Infinity  預設是對所有chunk進行提取;

function(module, count) => boolean  自定義提取的規則

minChunks取值需大於2,小於chunks的長度(即chunks配置項的長度或所有入口的長度)

minSize: number複製程式碼

在公共模組建立之前,所有 公共模組的最小大小

children: boolean複製程式碼

如果設定為 true,所有 公共chunk 的子模組都會被選擇;一般不設定這個值,畢竟我們值為了對公共程式碼的抽離,而不是想要全部抽離;不過這個也要針對不同的專案來處理,畢竟配置這個東西也是很自由的;

async:boolean|string複製程式碼

這個暫時沒有研究出來是什麼.....

具體配置

這個的配置一點也不復雜,主要是要根據實際情況進行配置比較複雜,情況一般分成下面幾種

  1. 專案是單入口應用還是多入口應用,這決定你是否合適使用CommonsChunkPlugin  

  2. 對哪些入口chunk進行提取,這決定了 nameschunkschildren配置項的設定

  3. 提取的粒度,這決定了minChunksminSize配置項的設定

基本上根據上面幾條,然後配置entry以及plugin就OK了,抽取的思路文章開頭也提到了,所以就不列舉各種情況了

// 提取公共程式碼主要修改的範圍如下,
// manifest 的提取是把webpack啟動執行部分程式碼,把部分程式碼抽離出來,
// 那每次業務程式碼有修改時,並不會影響到這個檔案的hash,那就可以持久化在瀏覽器,減少使用者載入的流量
module.exports = {  
  entry: {    
    main: ['./src/index.js'],    
    vendor: ['react']  
  },  
  plugins: [    
    new webpack.optimize.CommonsChunkPlugin({      
      names:['vendor', 'manifest'],          
      children: false,     // 是否對所有源chunks的子模組都包含          
      minChunks: 2,        // 提取程式碼的粒度          
      // chunks: [],       // 需要提取公共程式碼的源chunks     
    }),  
  ]
}

複製程式碼


相關文章