一般狀況下咱們的 WebApp 是有咱們的自身代碼和第三方庫組成的,咱們自身的代碼是會經常變更的,而第三方庫除非有較大的版本升級,否則是不會變的,因此第三方庫和咱們的代碼須要分開打包,咱們能夠給第三方庫設置一個較長的強緩存時間,這樣就不會頻繁請求第三方庫的代碼了。javascript
那麼如何提取第三方庫呢?在 webpack4.x 中, SplitChunksPlugin 插件取代了 CommonsChunkPlugin 插件來進行公共模塊抽取,咱們能夠對SplitChunksPlugin 進行配置進行 拆包 操做。html
SplitChunksPlugin配置示意以下:前端
optimization: {
splitChunks: { chunks: "initial", // 代碼塊類型 必須三選一: "initial"(初始化) | "all"(默認就是all) | "async"(動態加載) minSize: 0, // 最小尺寸,默認0 minChunks: 1, // 最小 chunk ,默認1 maxAsyncRequests: 1, // 最大異步請求數, 默認1 maxInitialRequests: 1, // 最大初始化請求書,默認1 name: () => {}, // 名稱,此選項課接收 function cacheGroups: { // 緩存組會繼承splitChunks的配置,可是test、priorty和reuseExistingChunk只能用於配置緩存組。 priority: "0", // 緩存組優先級,即權重 false | object | vendor: { // key 爲entry中定義的 入口名稱 chunks: "initial", // 必須三選一: "initial"(初始化) | "all" | "async"(默認就是異步) test: /react|lodash/, // 正則規則驗證,若是符合就提取 chunk name: "vendor", // 要緩存的 分隔出來的 chunk 名稱 minSize: 0, minChunks: 1, enforce: true, reuseExistingChunk: true // 可設置是否重用已用chunk 再也不建立新的chunk } } } } 複製代碼
SplitChunksPlugin 的配置項不少,能夠先去官網瞭解如何配置,咱們如今只簡單列舉了一下配置元素。vue
若是咱們想抽取第三方庫能夠這樣簡單配置java
splitChunks: {
chunks: 'all', // initial、async和all minSize: 30000, // 造成一個新代碼塊最小的體積 maxAsyncRequests: 5, // 按需加載時候最大的並行請求數 maxInitialRequests: 3, // 最大初始化請求數 automaticNameDelimiter: '~', // 打包分割符 name: true, cacheGroups: { vendor: { name: "vendor", test: /[\\/]node_modules[\\/]/, //打包第三方庫 chunks: "all", priority: 10 // 優先級 }, common: { // 打包其他的的公共代碼 minChunks: 2, // 引入兩次及以上被打包 name: 'common', // 分離包的名字 chunks: 'all', priority: 5 }, } }, 複製代碼
這樣彷佛大功告成了?並無,咱們的配置有很大的問題:node
下圖示意瞭如何將第三方庫進行拆包,基礎型的 react 等庫與工具性的 lodash 和特定庫 Echarts 進行拆分react
cacheGroups: {
reactBase: { name: 'reactBase', test: (module) => { return /react|redux/.test(module.context); }, chunks: 'initial', priority: 10, }, utilBase: { name: 'utilBase', test: (module) => { return /rxjs|lodash/.test(module.context); }, chunks: 'initial', priority: 9, }, uiBase: { name: 'chartBase', test: (module) => { return /echarts/.test(module.context); }, chunks: 'initial', priority: 8, }, commons: { name: 'common', chunks: 'initial', priority: 2, minChunks: 2, }, } 複製代碼
咱們對 chunk 進行 hash 化,正以下圖所示,咱們變更 chunk2 相關的代碼後,其它 chunk 都沒有變化,只有 chunk2 的 hash 改變了webpack
output: {
filename: mode === 'production' ? '[name].[chunkhash:8].js' : '[name].js', chunkFilename: mode === 'production' ? '[id].[chunkhash:8].chunk.js' : '[id].js', path: getPath(config.outputPath) } 複製代碼
咱們經過 http 緩存+webpack hash 緩存策略使得前端項目充分利用了緩存的優點,可是 webpack 之因此須要傳說中的 webpack配置工程師 是有緣由的,由於 webpack 自己是玄學,仍是以上圖爲例,若是你 chunk2的相關代碼去除了一個依賴或者引入了新的可是已經存在工程中依賴,會怎麼樣呢?git
咱們正常的指望是,只有 chunk2 發生變化了,可是事實上是大量不相干的 chunk 的 hash 發生了變更,這就致使咱們緩存策略失效了,下圖是變動後的 hash,咱們用紅圈圈起來的都是 hash 變更的,而事實上咱們只變更了 chunk2 相關的代碼,爲何會這樣呢?github
webpack hash緩存相關內容建議閱讀此文章 做爲拓展