您好,登錄后才能下訂單哦!
本篇內容主要講解“splitChunks怎么分割降低包大小”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“splitChunks怎么分割降低包大小”吧!
講解開始之前,大家先看一個問題。如果你已經知道問題的答案,而且明白為什么,就不必往下閱讀了。如果不知道答案或者知道答案,但不知道原因。那么,強烈建議閱讀本文。
// webpack.config.js const path = require("path"); const HtmlWebpackPlugin = require("html-webpack-plugin"); module.exports = { entry: { app: "./src/index.js" }, output: { filename: "[name].js", path: path.resolve(__dirname, "dist") }, optimization: { splitChunks: { chunks: "all" } }, plugins: [ new HtmlWebpackPlugin() ] };
// index.js import "vue" import(/*webpackChunkName: 'a' */ "./a"); import(/*webpackChunkName: 'b' */ "./b");
// a.js import "vue-router"; import "./someModule"; // 模塊大小大于30kb
// b.js import "vuex"; import "./someModule"; // 模塊大小大于30kb
// someModule.js // 該模塊大小超過30kb // ...
webpack 中以下三種常見的代碼分割方式:
入口起點:使用 entry
配置手動地分離代碼。
動態導入:通過模塊的內聯函數調用來分離代碼。
防止重復:使用 splitChunks
去重和分離 chunk。 第一種方式,很簡單,只需要在 entry
里配置多個入口即可:
entry: { app: "./index.js", app1: "./index1.js" }
第二種方式,就是在代碼中自動將使用 import()
加載的模塊分離成獨立的包:
//... import("./a"); //...
第三種方式,是使用 splitChunks
插件,配置分離規則,然后 webpack
自動將滿足規則的 chunk
分離。一切都是自動完成的。
前兩種拆分方式,很容易理解。本文主要針對第三種方式進行討論。
splitChunks: { // 表示選擇哪些 chunks 進行分割,可選值有:async,initial和all chunks: "async", // 表示新分離出的chunk必須大于等于minSize,默認為30000,約30kb。 minSize: 30000, // 表示一個模塊至少應被minChunks個chunk所包含才能分割。默認為1。 minChunks: 1, // 表示按需加載文件時,并行請求的最大數目。默認為5。 maxAsyncRequests: 5, // 表示加載入口文件時,并行請求的最大數目。默認為3。 maxInitialRequests: 3, // 表示拆分出的chunk的名稱連接符。默認為~。如chunk~vendors.js automaticNameDelimiter: '~', // 設置chunk的文件名。默認為true。當為true時,splitChunks基于chunk和cacheGroups的key自動命名。 name: true, // cacheGroups 下可以可以配置多個組,每個組根據test設置條件,符合test條件的模塊,就分配到該組。模塊可以被多個組引用,但最終會根據priority來決定打包到哪個組中。默認將所有來自 node_modules目錄的模塊打包至vendors組,將兩個以上的chunk所共享的模塊打包至default組。 cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, priority: -10 }, // default: { minChunks: 2, priority: -20, reuseExistingChunk: true } } }
以上配置,概括如下4個條件:
模塊在代碼中被復用或者來自 node_modules
文件夾
模塊的體積大于等于30kb(壓縮之前)
當按需加載 chunks 時,并行請求的最大數量不能超過5
初始頁面加載時,并行請求的最大數量不能超過將3
// index.js import("./a"); // ...
// a.js import "vue"; // ...
以上代碼,在默認配置下的構建結果如下:
原因分析:
index.js
作為入口文件,屬于入口起點手動配置分割代碼的情況,因此會獨立打包。(app.js)
a.js
通過 import()
進行加載,屬于動態導入的情況,因此會獨立打出一個包。(1.js)
vue
來自 node_modules
目錄,并且大于30kb;將其從 a.js
拆出后,與 a.js
并行加載,并行加載的請求數為2,未超過默認的5;vue
拆分后,并行加載的入口文件并無增加,未超過默認的3。vue
也符合 splitChunks
的拆分條件,單獨打了一個包(2.js)
chunks
用以告訴 splitChunks
的作用對象,其可選值有 async
、 initial
和 all
。默認值是 async
,也就是默認只選取異步加載的chunk進行代碼拆分。這個我們在開頭的例子里已經驗證。這里我們通過兩個例子來看一下當chunks的值為 initial
和 all
時,打包結果如何。 首先將chunks值改為 initial
:
chunks: "initial"
構建結果如下:
原因分析:
當 chunks
值為 initial
時,splitChunks
的作用范圍變成了非異步加載的初始 chunk,例如我們的 index.js
就是初始化的時候就存在的chunk。而 vue 模塊是在異步加載的chunk a.js
中引入的,所以并不會被分離出來。
chunks
仍使用 initial
, 我們對 index.js
和 a.js
稍作修改:
// index.js import 'vue' import('./a')
// a.js console.log('a')
構建結果如下:
原因分析:
vue
在 index.js
直接被引入,而 index.js
是初始chunk,所以分離出來打到了 vendors~app.js
中。
能不能讓 splitChunks
既處理初始chunk也處理異步chunk呢?答案是可以,只需要將 chunks
改為 all
:
chunks: "all"
對 index.js
和 a.js
稍作修改:
// index.js import 'vue-router' import('./a')
// a.js import 'vue' console.log('a')
構建結果如下:
原因分析:
chunks
值為 all
時,splitChunks
的處理范圍包括了初始chunk和異步chunk兩種場景,因此 index.js
中的 vue-router
被分拆到了 vendors~app.js
中,而異步加載的chunk a.js
中的 vue
被分拆到了 3.js
中。推薦在開發中將 chunks
設置為 all
。
maxIntialRequests
表示 splitChunks
在拆分chunk后,頁面中需要請求的初始chunk數量不超過指定的值。所謂初始chunk,指的是頁面渲染時,一開始就需要下載的js,區別于在頁面加載完成后,通過異步加載的js。
對 splitChunks
做以下修改,其他使用默認配置:
chunks: 'initial', maxInitialRequests: 1
對 index.js 稍作修改:
// index.js import 'vue'
構建結果如下:
原因分析:
因為 maxInitialRequests
為1,如果 vue
從 index.js
中拆出的話,新創建的chunk作為初始chunk index.js
的前置依賴,是需要在頁面初始化的時候就先請求的。那么初始化時的請求數變成了2,因此不滿足拆分條件,所以 splitChunks
沒有對 index.js
進行拆分。
與 maxInitialRequests
相對,maxAsyncRequests
表示 splitChunks
在拆分chunk后,并行加載的異步 chunk 數不超過指定的值。
對 splitChunks
做以下修改,其他使用默認配置:
maxAsyncRequests: 1
對 index.js
稍作修改:
// index.js import('./a')
// a.js import 'vue' console.log('a')
構建結果如下:
原因分析: 因為 maxAsyncRequests
為1,由于 a.js
是通過 import()
異步加載的,此時并行的異步請求數是1。如果將 vue
從 a.js
中拆出的話,拆出的包也將成為一個異步請求chunk。這樣的話,當異步請求 a.js
的時候,并行請求數有2個。因此,不滿足拆分條件,所以 splitChunks
沒有對 a.js
進行拆分。
minChunks
表示一個模塊至少應被指定個數的 chunk 所共享才能分割。默認為1。
對 splitChunks
做以下修改,其他使用默認配置:
chunks: 'all', minChunks: 2
對 index.js
稍作修改:
// index.js import 'vue'
構建結果如下:
原因分析:
因為 minChunks
為 2,所以只有當 vue
至少被2個 chunk 所共享時,才會被拆分出來。
思考題
請問如下代碼,構建結果是什么?
chunks: 'all', minChunks: 2
// index.js import 'vue' import './a'
// a.js import 'vue' console.log('a')
cacheGroups
繼承 splitChunks
里的所有屬性的值,如 chunks
、minSize
、minChunks
、maxAsyncRequests
、maxInitialRequests
、automaticNameDelimiter
、name
,我們還可以在 cacheGroups
中重新賦值,覆蓋 splitChunks
的值。另外,還有一些屬性只能在 cacheGroups
中使用:test
、priority
、reuseExistingChunk
。
通過 cacheGroups
,我們可以定義自定義 chunk 組,通過 test
條件對模塊進行過濾,符合條件的模塊分配到相同的組。
cacheGroups
有兩個默認的組,一個是 vendors
,將所有來自 node_modules
目錄的模塊;一個 default
,包含了由兩個以上的 chunk 所共享的模塊。
前面的例子中,你可能注意到了怎么有的拆分出的chunk名字這么奇怪,例如 vendors~app
(默認由 cacheGroups
中組的 key + 源chunk名組成)。我們看一下如何自定義拆分出的chunk名。
首先找到該chunk所屬的分組,該例為 vendors
分組,作如下修改,其他使用默認配置:
chunks:'all', cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, name: "customName", priority: -10 } }
對 index.js 稍作修改:
// index.js import 'vue'
構建結果如下:
原因分析:
vue 來自 node_modules
目錄,被分配到了默認的 vendors
組中,如果不指定 name
的話,會使用默認的chunk名,這里我們指定了 name
,因此最終的chunk名為customName
。
模塊還可以分配到多個不同的組,但最終會根據 priority
優先級決定打包到哪個 chunk。
新增一個分組:
chunks:'all', cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, name: "customName", priority: -10 }, customGroup: { test: /[\\/]node_modules[\\/]/, name: "customName1", priority: 0 } }
構建結果:
原因分析:
雖然 vendors
和 customGroup
這個兩個組的條件都符合,但由于后者的優先級更高,所以最終將 vue
打包到了 customName1.js
中。
到此,相信大家對“splitChunks怎么分割降低包大小”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。