uniapp分包(詳盡版)

PS:本文是筆者對基於uniapp的一小程式項目進行分包後的復盤文檔,不足之處請多多指教。

一:分包相關概念

  1. 本質上是改變項目的路由以及優化項目各個模組的啟動時間的一種優化技術。

  2. 主包與分包的概念

1). 主包:本項目中初始化時所必須的頁面。

項目在啟動時,將從主包進入,分包在用戶未進入時不會載入,只有在進入分包模組時才會載入。
tabbar頁面以及模組間共有的頁面,如果該項目有帳號限制(即非註冊帳號不可進入主介面),也應將登錄頁放置在主包內

2). 分包:除主包外的所有頁面都應放置在分包內,為避免讀者混淆,本文會將該分包定義為子包

二:為什麼要分包

優化項目首次啟動的下載時間;小程式默認就是整包(主包)下載,但這會導致整個項目只有在全部載入完畢後才會回顯到用戶眼前,這樣雖然可以使用載入動畫進行優化,但也會有部分可能導致用戶流失;

防止項目超出小程式官方對小程式項目打包後的大小限制;

若不分包,整個程式最大限制不能超過2M,分包後,整個項目(包含主包+子包)最大不能超過16M,單個包不能超過2M (這樣就規避了項目最大不得超過2m的限制)

三: 分包基本邏輯

  • 靜態文件:分包下支援 static 等靜態資源拷貝,即分包目錄內放置的靜態資源不會被打包到主包中,也不可在主包中使用
  • js文件:當某個 js 僅被一個分包引用時,該 js 會被打包到該分包內,否則仍打到主包(即被主包引用,或被超過 1 個分包引用)
  • 自定義組件:若某個自定義組件僅被一個分包引用時,且未放入到分包內,編譯時會輸出提示資訊

四: 分包步驟詳解

PS: 由於筆者僅做了微信小程式分包,因而以下也僅對面向微信小程式的uniapp項目有效

PS: 筆者是tabbar頁作為單模組劃分子包,即每個tabbar均作為一個子包模組

  1. (manifest.json ) 開啟分包優化

添加相關欄位

// "mp-weixin"
"optimization":{ 
      "subPackages":true //是否啟用分包優化
}

  1. (pages.json) 聲明項目分包結構
  • pages:

原則:pages內只允許存放tabbar頁面路由,以及各個子包所共有的頁面頁面,如果有登錄頁且不登錄無法進入主頁面,該登錄頁面路由也應放置在pages路由內

  • subPackages:

定義:單個模組內的除主包內文件的所有的文件,

比如: 假設一個tabbar模組內原本有index(tabbar頁).vue,notice.vue,about.vue這三個頁面,將index.vue這個頁面路由放置pages.json中的pages數組內,對應的將index.vue放置在項目中的pages目錄內
假設notice.vue與about.vue沒有在別的tabbar模組中被使用,則應該將notice.vue和about.vue兩個頁面文件放置在subPackages中
若notice.vue與about.vue這兩個頁面中有被別的模組使用,則同樣應該將其放置在pages主包內,為防止其與其他tabbar頁面混淆,應該在pages目錄內再單獨開闢一個目錄專門用於存放共有頁

弄懂了以上原則,接下來便可以實踐一下了

(pages.json)內新增subPackages欄位,與pages同級,同樣是數組格式,期內每一個對象均對應tabbar內的每一個模組,

(項目目錄)每一個對象都應在項目中生成每一個目錄,這個目錄與pages目錄同級

//pages.json
"pages":[
//這裡僅存放tabbar,以及公共頁
],
"subPackages":[
//subPackages數組裡的每一個對象都代表了對應tabbar模組里的除tabbar中index.vue以外所有的頁面,且該數組裡每一個對象都在項目目錄中與pages目錄平級
      //舉個栗子  這裡是首頁模組,index.vue由於是tabbar頁面,故而被放置在了pages.json中,剩餘兩個文件並沒有被其他tabbar模組使用,因而被放置在了這裡
      {
            "root":"pages_Index", //這裡代表根目錄的映射,表示在項目中這個模組的根目錄也就是上面說的與pages目錄平級的目錄名
            "pages":[ // 這裡的pages表示分包內的頁面,凡在該子包的pages目錄下,均不可被其他子包模組訪問
                  //這裡指的是原本從pages頁中遷移來的,僅本模組專屬的頁面,其格式規範遵循tabbar所在pages數組規範
                  {
                         // 網上有人說path路徑必須由pages_Index根目錄開始,但是在實踐過程中發現不從根目錄開始也可以,原因猜測是root本身已定義了根目錄
                         // 原目錄為: /pages_index/packet/notice
			path":"packet/notice", 
			"style": {
				"navigationBarTitleText": "我是子包文件"
			}
		 },                 
            ]
      
      }


]

目錄結構如下:

pages.json如下:

這樣便完成了配置的第二步

  1. 更換各個頁面路由

筆者之前一直強調的分包越早越好的原因就在於此,一但項目到了微信2m限制,則會直接導致項目無法在開發者工具中運行,雖然分包可以在整個項目周期任一進度進行,但是需花費的時間是與項目進度是成正比的,即項目進度越到尾期,則分包需要花費的時間也就越長,筆者對此深有體會(流眼淚.jpg)
如果在項目中末期才進行分包,此時需要開發者站在整個項目角度上,對每個模組,每個頁面,每個網路請求都要瞭然於胸,可以藉助于思維導圖工具,將項目所有模組所有頁面都列出來,剔除tabbar頁面和模組間共有頁面,然後將剩餘頁面填充至指定子包目錄下,並在subPackages目錄下聲明該頁面路徑,並且,開發者必須要重新定義路由跳轉路徑以及組件引入方式,這一點極為繁瑣,且極易出錯造成損失,因而建議開發者在走這一步前預先做好備份。

導入組件路徑建議直接更換成以@開頭的絕對路徑來替換省略號開頭的相對路徑,防止以後可能再次發生的變更

跳轉路由也應換成絕對路徑,(路由更換後跳轉失敗? 請點擊這裡

在本過程中,可能會出現各種引用錯誤或者無法跳轉的問題,此時需要開發者心態平緩,並一定要謹慎檢查

如果在開發者工具中運行整個項目顯示沒有報錯資訊,則可以在真機調試,如果有短時彈框 「 載入模組中 」,則表示分包成功

那麼問題來了:我不想用戶看到這幾個醜陋的字,該怎麼做?

出現這幾個字的原因是由於用戶剛進入的介面必定是主包,而在用戶進入分包的時候,由於分包資源還未下載,所以微信官方便貼心的提示用戶正在載入分包資源
筆者:微信我謝謝你呀!(超大聲嗶嗶)
那麼接下來要說的,就是關於這類問題的解決辦法: 分包預載入

  1. (pages.json)實現分包預載入

定義:在用戶進入某個頁面時,同時靜默下載跟該頁面有關的子包文件

與subPackages平級添加preloadRule對象,
該對象內部的key指的是某個頁面路徑,也就是當用戶進入某個頁面時,需要預載入的頁面路徑,
value

//pages.json
//以子包pages_index為例
"subPackages":[
//分包模組
      {
            "root" : "pages_index",
            "pages" : [
                {
                   "path" : "packet/notice",
                   "style" : { "navigationBarTitleText": "我是子包頁面"}
                }  
            ]
      }
],
"preloadRule" :{
      "pages/index/index":{ //要進行預載入時用戶要進入的頁面路徑
            "network":"all", // 什麼網路下支援允許預載入,默認wifi:   wifi/all
            "packages":["pages_Index"] // 要進行預載入的子包名
	},
}

使用分包預載入功能,
如果配置成功,開發者console控制台會輸出以下資訊:

  1. 幾點原則
  1. 主包可以引用分包內文件,分包僅可引用自身目錄內的文件,分包與分包間文件無法互相引用,
  1. 要清楚的是分包是一種不得已而為之的手段,確保在分包前項目中靜態資源已優化完畢,且沒有大量注釋或無用程式碼也是一種手段

————————-假裝這是一條分割線———————————————————-

這篇文章是筆者在復盤項目時的心得,不足之處歡迎在評論區指教,不勝感激

以上。

Tags: