1. 程式人生 > 前端設計 >H5 分包實現首屏載入時間優化

H5 分包實現首屏載入時間優化

H5 分包實現首屏載入時間優化

一、為什麼首屏載入需要優化

因為做了很多事情:

初始化 webView -> 請求頁面 -> 下載資料 -> 解析HTML -> 請求 js/css 資源 -> dom 渲染 -> 解析 JS 執行 -> JS 請求資料 -> 解析渲染 -> 下載渲染圖片

dom渲染 之前使用者看到的都是白屏,在 下載渲染圖片 後,使用者才能看到完整的頁面。首屏秒開優化就是要減少這個過程的耗時。

扣除網路差的原因,對首屏啟動速度影響最大的就是網路請求。由於業務需求,導致我們不得不引入很多第三方包來實現功能,這些包恰恰會容易影響到網路請求。

這裡我們把大體積的包,分成多個小體積的包進行載入,減少請求時間

二、分析產物

通過分析產物來檢視打出來的包內容佔比

yarn build複製程式碼

打完包後如果出現下面黃色文字,說明打出來的包體積過大,我們用百度翻譯來看下解釋:

在這裡插入圖片描述


束的大小明顯大於推薦值。
考慮使用程式碼拆分來減少它:https://goo.gl/9VhYWB
您還可以分析專案依賴關係:https://goo.gl/LeUzfb複製程式碼

你的包大小超過了推薦值,可以通過分析專案依賴進行的分包處理。

umialita 專案中,執行 ANALYZE=1 umi buildANALYZE=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: 拆分塊的名稱,提供字串或函式使您可以使用自定義名稱,如果 namechunks 名稱匹配,則進行拆分。

  • 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 點一點呀~