webpack4分包方案


webpack4放棄了 commonsChunkPlugin,使用更方便靈活智能的 splitChunks 來做分包的操作。

下面有幾個例子,並且我們假設所有的chunks大小至少為30kb(采用splitChunks默認配置)

vendors

入口

chunk-a: react react-dom 其他組件

chunk-b: react react-dom 其他組件

chunk-c: angular 其他組件

chunk-d: angular 其他組件

產出

vendors-chunk-a-chunk-b: react react-dom

vendors-chunk-c-chunk-d: angular

chunk-a 至 chunk-d: 對應的其他組件

重復的vendors

入口

chunk-a: react react-dom 其他組件

chunk-b: react react-dom lodash 其他組件

chunk-c: react react-dom lodash 其他組件

產出

vendors-chunk-a-chunk-b-chunk-c: react react-dom

vendors-chunk-b-chunk-c: lodash

chunk-a 至 chunk-c: 對應的其他組件

模塊

入口

chunk-a: vue 其他組件 shared組件

chunk-b: vue 其他組件 shared組件

chunk-c: vue 其他組件 shared組件

假設這里的shared體積超過30kb,這時候webpack會創建vendors和commons兩個塊

產出

vendors-chunk-a-chunk-b-chunk-c: vue

commons-chunk-a-chunk-b-chunk-c: shared組件

chunk-a 至 chunk-c: 對應的其他組件

如果shared提交小於30kb,webpack不會特意提出來,webpack認為如果僅僅為了減少下載體積的話,這樣做是不值得的。

多個共享模塊

入口

chunk-a: react react-dom 其他組件 react組件

chunk-b: react react-dom angular 其他組件

chunk-c: react react-dom angular 其他組件 react組件 angular組件

chunk-d: angular 其他組件 angular組件

產出

vendors-chunk-a-chunk-b-chunk-c: react react-dom

vendors-chunk-b-chunk-c-chunk-d: angular

commons-chunk-a-chunk-c: react組件

commons-chunk-c-chunk-d: angular組件

chunk-a 至 chunk-d: 對應的其他組件

關於webpack默認配置

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
      }
    }
}
  • chunks: 表示從哪些chunks里抽取代碼,有三個值:
    1. initial:初始塊,分開打包異步\非異步模塊
    2. async:按需加載塊, 類似initial,但是不會把同步引入的模塊提取到vendors中
    3. all:全部塊,無視異步\非異步,如果有異步,統一為異步,也就是提取成一個塊,而不是放到入口文件打包內容中

通過import()控制模塊的一些屬性

initial情況下,如果兩個入口一個是同步引入,一個是異步引入,那么會分開打包,同步的直接將引入包打到入口文件的打包文件里,異步的會分出單獨的塊,按需引入
all情況下,如果一個異步一個同步,會統一分出一個單獨的塊,然后引入

  • minSize代表最小塊大小,如果超出那么則分包,該值為壓縮前的。也就是先分包,再壓縮
  • minchunks表示最小引用次數,默認為1
  • maxAsyncRequests: 按需加載時候最大的並行請求數,默認為5
  • maxInitialRequests: 一個入口最大的並行請求數,默認為3
  • automaticNameDelimiter表示打包后人口文件名之間的連接符
  • name表示拆分出來塊的名字
  • cacheGroups:緩存組,除了上面所有屬性外,還包括
    • test:匹配條件,只有滿足才會進行相應分包,支持函數 正則 字符串
    • priority:執行優先級,默認為0
    • reuseExistingChunk:如果當前代碼塊包含的模塊已經存在,那么不在生成重復的塊

幾種配置示例(依賴優先級priority)

個人感覺其實只要玩好cacheGroups,就能完成各種各樣的分包
// 將所有node_modules中應用2次以上的抽成common塊
optimization: {
  splitChunks: {
    cacheGroups: {
      common: {
        test: /[\\/]node_modules[\\/]/,
        name: 'common',
        chunks: 'initial',
        priority: 2,
        minChunks: 2
      }
    }
  }
}
// 把所有超過2次的達成common,不局限於node_modules
optimization: {
  cacheGroups: {
    common: {
      name: 'common',
      chunks: 'initial',
      priority: 2,
      minChunks: 2,
    }
  }
}
// 額外提取react相關基礎模塊,然后抽取引入超過兩次的模塊到common
optiomization: {
  cacheGroups: {
    reactBase: {
      name: 'reactBase',
      test: (module) => {
          return /react|redux|prop-types/.test(module.context);
      },
      chunks: 'initial',
      priority: 10,
    },
    common: {
      name: 'common',
      chunks: 'initial',
      priority: 2,
      minChunks: 2,
    }
  }
}
// 如果提取出來的包依然很大,你又想利用好緩存,你可以這樣做
// 這樣你的每一個node_modules包都是一個chunks,對緩存很友好,會節約很多用戶流量,雖然流量已經不之前
optimization: {
  cacheGroups: {
    vendor: {
      test: /[\\/]node_modules[\\/]/,
      name(module) {
        const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];
        // 避免服務端不支持@
        return `npm.${packageName.replace('@', '')}`;
      },
    },
  }
}

相關文章

Code Splitting, chunk graph and the splitChunks optimization
webpack4 splitchunks實踐探索
chunks解釋
vendors過大的解決方案


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM