H5 分包實現首屏載入時間優化
H5 分包實現首屏載入時間優化
一、為什麼首屏載入需要優化
因為做了很多事情:
初始化 webView -> 請求頁面 -> 下載資料 -> 解析HTML -> 請求 js/css 資源 -> dom 渲染 -> 解析 JS 執行 -> JS 請求資料 -> 解析渲染 -> 下載渲染圖片
在 dom渲染
之前使用者看到的都是白屏,在 下載渲染圖片
後,使用者才能看到完整的頁面。首屏秒開優化就是要減少這個過程的耗時。
扣除網路差的原因,對首屏啟動速度影響最大的就是網路請求。由於業務需求,導致我們不得不引入很多第三方包來實現功能,這些包恰恰會容易影響到網路請求。
這裡我們把大體積的包,分成多個小體積的包進行載入,減少請求時間
二、分析產物
通過分析產物來檢視打出來的包內容佔比
yarn build複製程式碼
打完包後如果出現下面黃色文字,說明打出來的包體積過大,我們用百度翻譯來看下解釋:
束的大小明顯大於推薦值。 考慮使用程式碼拆分來減少它:https://goo.gl/9VhYWB 您還可以分析專案依賴關係:https://goo.gl/LeUzfb複製程式碼
你的包大小超過了推薦值,可以通過分析專案依賴進行的分包處理。
在 umi
和 alita
專案中,執行 ANALYZE=1 umi build
或 ANALYZE=1 alita build
來分析下產物。
我們可以看到經過壓縮後的 umi.js
還有 1.2M
的大小。
umi.js
下最大的包是筆者引入的 echarts
,有 211kb
的大小,這裡只是引入了一個 echart
包,如果專案中,多引入一些大體積包的話,那麼 umi.js
的大小就不是 1M
而會更大,在首屏載入時,請求這些資料就嚴重影響到了下載和渲染時間。
這時,對包的拆解就顯得尤為重要了。
三、分包實現
開啟 config/config.ts
檔案(如果是 umi2
的專案則是 .umirc.js
)
export default { chainWebpack(config) { config.optimization.splitChunks({ chunks: 'all',automaticNameDelimiter: '~',name: true,minSize: 30000,minChunks: 1,cacheGroups: {echarts: { name: 'echarts',test: /[\\/]node_modules[\\/](echarts)[\\/]/,priority: -9,enforce: true,},vendors: { name: 'vendors',test: /[\\/]node_modules[\\/]/,priority: -11,} }) },chunks: ['vendors','echarts','umi'],}複製程式碼
我們先看下 cacheGroups
下的屬性,其他屬性在下文中會講解,先實現需求為重。
cacheGroups
下的屬性為 key-value
的物件形式,key
可以自行命名,那 value
的值呢,我們繼續往下看:
name
: 拆分塊的名稱,提供字串或函式使您可以使用自定義名稱,如果name
與chunks
名稱匹配,則進行拆分。test
: 正則匹配路徑,符合入口的都會被拆分,裝到name
名稱下的包中。priority
: 拆包的優先順序,越大優先順序越高。順序很重要,先把大包分出去,在將剩餘的node_modules
分成vendors
包。enforce
: 不管這個包的大小,都會進行分包處理。
現在我們再執行 ANALYZE=1 umi build
看看效果:
echarts
包已經從 umi.js
中拆分出來,umi.js
的大小縮小到 800K
左右,這時通過 yarn build
打包不會才提示包過大的內容了。但是為了進一步演示,我們可以把上圖中較大的包如 antd-mob ile
或者 antd
元件庫的包也分出來。
在上面的程式碼 cacheGroups
中補充:
antdm: { name: 'antdm',chunks: 'all',test: /[\\/]node_modules[\\/](@ant-design|antd|antd-mobile)[\\/]/,// 這裡模擬有 antd 的情況,請根據實際專案具體考慮分析 priority: -10,複製程式碼
chunks: ['vendors','umi','antdm'],複製程式碼
由圖得知,元件庫的包被分出來了 umi.js
由變小了一點點。
這裡補充一點呢,不建議拆分太小包,比如上述的 antdm
因為意義不大。
四、解析 splitChunks
第三大點,我們著重分析了 cacheGroups
,現在我們來分析下其餘的欄位,官網文件有解析,不過感覺對於有些像我這樣的初學者來說閱讀起來會比較生澀一點,所以也可以下文中我對某些欄位的解釋,應該會來的通俗易懂一點點。
chunks
: 有效值為:all|async|initial
引數 | 含義 |
---|---|
all | 把動態和非動態模組同時進行優化打包;所有模組都扔到 vendors.bundle.js 裡面。 |
async | 把動態模組打包進 vendor,非動態模組保持原樣(不優化) |
initial | 把非動態模組打包進 vendor,動態模組優化打包 |
動態引入模組:
import ('lodash')
非動態引入模組:
import 'react'
筆者推薦一篇文章詳細講解了 chunks
引數的含義:webapck4 玄妙的 SplitChunks Plugin
maxAsyncRequests
: async
時並行請求的最大數量。在做一次按需載入的時候最多有多少個非同步請求,為 1 的時候就不會抽取公共 chunk 了
maxInitialRequests
: initial
時並行請求的最大數量。同上。
minChunks
: 拆分前必須共享模組的最小塊數。指某個模組最少被多少個入口檔案依賴。當大於等於minChunks設定的值時,該模組就會被打包到公用包中。小於這個值時,該模組就會被和每個入口檔案打包在一起。
minSize
: 被拆分出的bundle在拆分之前的體積的最小數值,只有 >= minSize
的bundle會被拆分出來。
maxSize
: 被拆分出的bundle在拆分之前的體積的最大數值,預設值為0,表示bundle在拆分前的體積沒有上限。maxSize如果為非0值時,切忌小於minSize。
star 點一點呀~