- webpack打包js代碼與提取公共js代碼分析
- webpack提取公共js代碼示例
一、分析
webpack默認打包js代碼時,是將從入口js模塊開始,將入口js模塊所依賴的js以及模塊逐層依賴的模塊,全部以入口js模塊為主體全部打包至生成的對應js文件中。即使是多個js入口依賴鏈模塊依賴了同一個模塊也會被重復打包至不同的js文件中,這種打包方式會產生比較大的代碼冗余。

通過上圖可以看到,A模塊會重復出現在bundle1、bundle2、bundle3中;B模塊雖然只被M3依賴,但是由於M3同時被三個入口模塊依賴,所以B模塊也會同時出現在最后生成的三個js文件中,到了M這一層,M3的代碼肯定會重復出現最后的三個js文件中,這個依賴模型圖就可以看出因為相互依賴,導致的打包時代碼冗余會很大。所以,提取公共js代碼是性能優化的重要方式。
關於提取公共js代碼並非是被依賴了多次就一定會被提取為公共代碼,暫且不討論這個並非是什么,先思考一個問題“如果一個模塊非常小,但被多個模塊依賴,是否就值得提取為公共代碼模塊呢?”
顯然,如果是一個非常小的模塊被提取為公共代碼是非常不合適的,相對計算機內存等硬件性能而言,網絡請求對系統性能的影響更大,因為網絡傳輸存在太多不能確定的因素,所以提取公共js代碼也會有一些(參數)約束,以求在相對的系統性能下達到系統性能的最佳狀態。
關於webpack4的系統優化詳細文檔手冊可以查看這里:https://webpack.docschina.org/configuration/optimization/
常用參數:
minSize(默認是30000):形成一個新代碼塊最小體積;
minChunks(默認是1):在分割之前,這個代碼最小應該被引用的次數(注:保證代碼塊復用性,默認配置的策略是不需要引用也可以被分割);
maxInitialRequests(默認是3):一個入口最大的並行請求數;
maxAsyncRequests(默認是5):按需加載時候最大的並行請求數;
chunks(默認是async):表示顯示塊的范圍,有三個可選值:initial(初始塊)、async(按需加載塊)、all(全部塊),默認為all;
test:用於控制哪些模塊被這個緩存組匹配到。原封不動傳遞出去的話,它默認會選擇所有的模塊。可以傳遞的值類型:RegExp、String和Function;
name(打包的chunks的名字):字符串或者函數(函數可以根據條件自定義名字);
priority:緩存組打包的先后優先級。
二、示例

示例工作區間的文件結構:
//工作區間 src//文件夾 module.js//自定義公共模塊 subPageA.js//業務邏輯代碼A subPageB.js//業務邏輯代碼B pageA.js//業務A的入口js pageB.js//業務B的入口js node_modules//打包環境公共包文件 lodash//lodash庫的包 package.json//配置環境信息 webpack.config.js//打包配置文件
各個文件的代碼(示例中只給出依賴關系):
module.js: export default 'module'; ;
PageA.js: import './subPageA'; var lodash = require('lodash'); ;
PageB.js: import './subPageB'; var lodash = require('lodash'); ;
subPageA.js: import './module'; export default 'subPageA'; ;
subPageB.js: import './module'; export default 'subPageB'; ;
打包配置文件webpack.config.js:
var path = require('path'); module.exports = { entry:{ pageA:'./src/pageA.js', pageB:'./src/pageB.js' }, output:{ path:path.resolve(__dirname,'dist'),//構建文件夾 filename:'[name][hash:5].bundle.js',//生成文件名稱 chunkFilename:'[name][hash:5].js' }, optimization:{//webpack4新增 splitChunks:{//可以在這里直接設置抽離代碼的參數,最后將符合條件的代碼打包至一個公共文件 cacheGroups:{//設置緩存組用來抽取滿足不同規則的chunk,下面以生成common、vender為例 // 根據不同的參數設置抽取不同條件的公共js common:{// name:'common', chunks:'all', minSize:1, minChunks:1, priority:1//設置匹配優先級,數字越小,優先級越低 }, vendor:{ name:'vender', test:/[\\/]node_modules[\\/]/,//匹配node模塊中匹配的的模塊 priority:10,//設置匹配優先級,數字越大,優先級越高 chunks:'all' } } } }, mode:'development' }
在示例中,以test作為提取條件,在priority:10大於priority:1的條件下優先提取了lodash並命名為vender作為一個公共js,然后再提取module.js,即使是lodash還符合common的提取條件,但由於已經有優先級高的提取了這部分代碼,就不會再重復提取。
關於webpack提取js代碼優化操作還有其他特性和參數沒有在示例中展示,需要進一步學習和了解webpack的打包操作建議參考前文中提供的手冊鏈接。
