代碼均放在git倉庫node
Webpack 4給咱們帶來了一些改變。包括更快的打包速度,引入了SplitChunksPlugin插件來取代(以前版本里的)CommonsChunksPlugin插件。在這篇文章中,你將學習如何分割你的輸出代碼,從而提高咱們應用的性能。react
SplitChunks插件(webpack 4.x之前使用CommonsChunkPlugin
)容許咱們將公共依賴項提取到現有的entry chunk
或全新的代碼塊中。webpack
首先搞明白: webpack裏的代碼分割是個什麼鬼? 它容許你將一個文件分割成多個文件。若是使用的好,它能大幅提高你的應用的性能。其緣由是基於瀏覽器會緩存你的代碼這一事實。每當你對某一文件作點改變,訪問你站點的人們就要從新下載它。然而依賴卻不多變更。若是你將(這些依賴)分離成單獨的文件,訪問者就無需屢次重複下載它們了。git
使用webpack生成一個或多個包含你源代碼最終版本的「打包好的文件」(bundles),(概念上咱們看成)它們由(一個一個的)chunks組成。github
首先 webpack 總共提供了三種辦法來實現 Code Splitting,以下:web
這裏咱們姑且只討論使用 SplitChunks 抽取公有代碼。npm
在src目錄下建立三個文件pageA.js、pageB.js和pageC.js。代碼詳情見文章開頭git倉庫。redux
// src/pageA.js
var react = require('react');
var reactDom = require('react-dom');
var utility1 = require('../utils/utility1');
var utility2 = require('../utils/utility2');
new Vue();
module.exports = "pageA";
複製代碼
// src/pageB.js
var react = require('react');
var reactDom = require('react-dom');
var utility2 = require('../utils/utility2');
var utility3 = require('../utils/utility3');
module.exports = "pageB";
複製代碼
// src/pageC.js
var react = require('react');
var reactDom = require('react-dom');
var utility2 = require('../utils/utility2');
var utility3 = require('../utils/utility3');
module.exports = "pageC";
複製代碼
entry: {
pageA: "./src/pageA", // 引用utility1.js utility2.js
pageB: "./src/pageB", // 引用utility2.js utility3.js
pageC: "./src/pageC", // 引用utility2.js utility3.js
},
output: {
path: path.join(__dirname, "dist"),
filename: "[name].[hash:8].bundle.js"
},
複製代碼
首先咱們配置optimization以下:數組
optimization: {
splitChunks: {
chunks: "all",
},
複製代碼
執行npm run build打包命令以後,查看dist目錄瀏覽器
能夠發現,打包出來的除了三個page文件,還存在一個vendors~pageA~pageB~pageC.[hash].bundle.js文件(此文件中保存了pageA、pageB、pageC和node_modules中共有的size大於30KB的文件)。事實上這全靠了配置中自己默認固有一個cacheGroups的配置項:
splitChunks: {
chunks: "all",
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/, // 匹配node_modules目錄下的文件
priority: -10 // 優先級配置項
},
default: {
minChunks: 2,
priority: -20, // 優先級配置項
reuseExistingChunk: true
}
}
}
複製代碼
在默認設置中,
參數說明以下:
值得注意的是,若是沒有修改minSize屬性的話,並且被公用的代碼(假設是utilities.js)size小於30KB的話,它就不會分割成一個單獨的文件。在真實情形下,這是合理的,由於(如分割)並不能帶來性能確實的提高,反而使得瀏覽器多了一次對utilities.js的請求,而這個utilities.js又是如此之小(不划算)。
緩存組會繼承splitChunks的配置,可是test、priorty和reuseExistingChunk只能用於配置緩存組。cacheGroups是一個對象,按上述介紹的鍵值對方式來配置便可,值表明對應的選項。除此以外,全部上面列出的選擇都是能夠用在緩存組裏的:chunks, minSize, minChunks, maxAsyncRequests, maxInitialRequests, name。能夠經過optimization.splitChunks.cacheGroups.default: false禁用default緩存組。默認緩存組的優先級(priotity)是負數,所以全部自定義緩存組均可以有比它更高優先級(譯註:更高優先級的緩存組能夠優先打包所選擇的模塊)(默認自定義緩存組優先級爲0)
如今咱們再從新來看一下pageA、pageB、pageC三個js文件,這三個文件中都引入了utility2.js文件,可是此文件size很明顯小於30KB,因此這部分公用代碼並無分割出來。若是想要分割出來很簡單,只須要:
optimization: {
splitChunks: {
chunks: "all",
minSize: 0
}
},
複製代碼
執行npm run build打包命令以後,查看dist目錄
顯然多了一個pageA~pageB~pageC.[hash].bundle.js文件。查看文件可得知此文件中存儲了utility2.js中的代碼。以下圖所示(藉助於webpack-bundle-analyzer插件,詳情文章末尾附錄)。
上圖能夠看出,React相關代碼均放在了vendors~pageA~pageB~pageC.[hash].bundle.js文件中,若是咱們想要抽離出React代碼,應該怎麼作吶?
splitChunks: {
chunks: "all",
cacheGroups: {
commons: {
chunks: "initial",
minChunks: 2,
name: "commons",
maxInitialRequests: 5,
minSize: 0, // 默認是30kb,minSize設置爲0以後
// 屢次引用的utility1.js和utility2.js會被壓縮到commons中
},
reactBase: {
test: (module) => {
return /react|redux|prop-types/.test(module.context);
}, // 直接使用 test 來作路徑匹配,抽離react相關代碼
chunks: "initial",
name: "reactBase",
priority: 10,
}
}
},
複製代碼
run build以後以下圖所示。
咱們再安裝一個 webpack-bundle-analyzer,這個插件會清晰的展現出打包後的各個bundle所依賴的模塊:
npm i webpack-bundle-analyzer -D
複製代碼
引入:
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
複製代碼
使用,在plugins數組中添加便可:
new BundleAnalyzerPlugin()
複製代碼