有夢想,有乾貨,微信搜尋 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。
本文 GitHub https://github.com/qq449245884/xiaozhi 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。
分包
什麼是分包
分包指的是把一個完整的小程式專案
,按照需求劃分為不同的子包
,在構建時打包成不同的分包,使用者在使用時按需進行載入。
分包的好處
對小程式進行分包的好處主要有以下兩點:
- 可以優化小程式首次啟動的下載時間
- 在多團隊共同開發時可以更好的解耦協作
uniapp 分包配置
按官網,假設支援分包的 uni-app
目錄結構如下:
┌─pages
│ ├─index
│ │ └─index.vue
│ └─login
│ └─login.vue
├─pagesA
│ ├─static
│ └─list
│ └─list.vue
├─pagesB
│ ├─static
│ └─detail
│ └─detail.vue
├─static
├─main.js
├─App.vue
├─manifest.json
└─pages.json
則需要在 pages.json 中填寫:
{
"pages": [{
"path": "pages/index/index",
"style": { ...}
}, {
"path": "pages/login/login",
"style": { ...}
}],
"subPackages": [{
"root": "pagesA",
"name": "分包的別名"
"pages": [{
"path": "list/list",
"style": { ...}
}]
}, {
"root": "pagesB",
"pages": [{
"path": "detail/detail",
"style": { ...}
}]
}],
}
動手實踐:https://github.com/qq44924588...
執行後,可以在開發者詳情裡檢視分包資訊:
這樣配置的目錄結構真的好?
按官網的事例,如果我們要分兩個包,則對在 pages 同級下建立兩個目錄 pagesA
、 pagesB
,這樣劃分真的好嗎?假設我們有一個活動的業務模板,對應 的活動詳情地址是 /pages/activity/detail
。pages.json
配置如下:
"pages": [
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "首頁"
}
},
{
"path": "pages/activity/detail",
"style": {
"navigationBarTitleText": "活動詳情"
}
}
],
隨著業務的發展,該模組的功能也越來越多。哪天,我們要對該包進行分包的時候,如果按照前面的分包方式,我們如果在 pages
同級下建立一個子包的目錄,假設我們這裡叫 pagesA
,然後把對應的活動模組的檔案都挪動到該目錄下,對應的 pages.json
配置如下:
"subPackages": [{
"root": "pagesA",
"pages": [{
"path": "activity/detail"
}]
}]
此時,對應的 活動詳情地址是 /pagesA/activity/detail
,這樣就會引發一個問題,此時活動詳情路徑已經變化了,所以分包要能正常工作,之前的路徑都要改過來,如果有其它小程式有跳到該詳情頁面也得改,顯然這種分包結構是很不靠譜的,為了一個分包得改多個檔案,甚至多個小程式。
那要怎麼解決這個問題了?顯然,只要路徑不變化,但能正確分包不就可以解決這個問題了。
在細想一下分包,無非就是在 subPackages
中指定一個分包名,分包頁面對應該分包名下的檔案。所以,我們可以指定原有 pages
下的模組作為一個子分包,這樣配置就可以解決分包後路徑不一致的問題,改寫後的結構如下:
"subPackages": [
{
"root": "pages/activity",
"pages": [
{
"path": "detail"
}
]
}
],
事例地址:https://github.com/qq44924588...
分包預載入
分包預載配置。配置 preloadRule
後,在進入小程式某個頁面時,由框架自動預下載可能需要的分包,提升進入後續分包頁面時的啟動速度。
假設,我們兩個分包 pagesA
和 pagesB
,當我們進入詳情頁面,想預先加 pagesA
,對應的配置如下:
{
"pages": [ //pages陣列中第一項表示應用啟動頁,參考:https://uniapp.dcloud.io/collocation/pages
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "首頁"
}
},
{
"path": "pages/detail/index",
"style": {
"navigationBarTitleText": "詳情"
}
}
],
"subPackages": [{
"root": "pagesA",
"pages": [{
"path": "detail/index"
}]
}, {
"root": "pagesB",
"pages": [{
"path": "detail/index"
}]
}],
"preloadRule": {
"pages/detail/index": {
"network": "wifi",
"packages": ["pagesA", "pagesB"]
}
}
}
preloadRule
中,key
是頁面路徑,value
是進入此頁面的預下載配置, packages
是進入頁面後預下載分包的 。network
在指定網路下預下載,可選值為:all(不限網路)、wifi(僅wifi下預下載)。
事例地址:
https://github.com/qq44924588...
分包的載入規則
分包需要注意一點是:tabBar
頁面需要放在主包中,假設我們如兩個 tabBar,配置如下:
{
"pages": [
{
"path": "pages/channel/index",
"style": {
"disableScroll": true
}
},
{
"path": "pages/member/index",
"style": {
"disableScroll": true
}
}
],
"tabBar": {
"color": "#BBBBBD",
"selectedColor": "#1C1C1C",
"borderStyle": "white",
"backgroundColor": "#ffffff",
"list": [
{
"pagePath": "pages/channel/index",
"iconPath": "static/tabbar_icon_channel.png",
"selectedIconPath": "static/tabbar_icon_channel_active.png",
"text": "會員專屬"
},
{
"pagePath": "pages/member/index",
"iconPath": "static/tabbar_icon_member.png",
"selectedIconPath": "static/tabbar_icon_member_active.png",
"text": "掌通會員"
}
]
}
}
如果我們把 tabBar 頁面配置到 subPackages
,則會出錯:
事例地址:https://github.com/qq44924588...
分包優化
在對應平臺的配置下新增"optimization":{"subPackages":true}
開啟分包優化。
分包優化具體邏輯
- 靜態檔案:分包下支援 static 等靜態資源拷貝,即分包目錄內放置的靜態資源不會被打包到主包中,也不可在主包中使用
- js檔案:當某個 js 僅被一個分包引用時,該 js 會被打包到該分包內,否則仍打到主包(即被主包引用,或被超過 1 個分包引用)
- 自定義元件:若某個自定義元件僅被一個分包引用時,且未放入到分包內,編譯時會輸出提示資訊
首先,我們來化驗一下第一條規則,首頁建立對應的配置:
{
"pages": [
{
"path": "pages/index/index",
}
],
"subPackages": [{
"root": "pagesA",
"pages": [{
"path": "detail/index"
}]
}],
}
這裡,我們有一個分包 pagesA
對應一個詳情頁面,詳情頁面使用一張圖片,該圖片放置當前包下 static
檔案下,內容如下:
<view class="content">
<image class="logo" src="../static/test.png" />
</view>
然後,我們開始打包,然後點選開發者工具的 詳情,點選 原生程式碼-> 依賴分析
,就可以檢視打包的詳細資訊,如下圖所示:
可以看到,我們點選 主包 下的 static
是沒有我們的在分包中用的 test.png
圖片,相反,它被打包自己的分包下面。即分包目錄內放置的靜態資源不會被打包到主包中,成立。
接下來,在來驗證一下,如果在主包中使用分包的 test.png
圖片會怎麼樣?改寫一上我們主包的 index
檔案的內容:
<view class="content">
<image class="logo" src="../../pagesA/static/test.png" />
</view>
執行後,控制檯會給出錯誤:
所以,分包下支援 static 等靜態資源拷貝,即分包目錄內放置的靜態資源不會被打包到主包中,也不可在主包中使用 成立。
事例地址:https://github.com/qq44924588...
然後,我們來驗證一下第二條規則:js檔案:當某個 js 僅被一個分包引用時,該 js 會被打包到該分包內,否則仍打到主包(即被主包引用,或被超過 1 個分包引用)。
首先,我們在主包中的 src/utils
中建立一個 common.ts
,內容如下:
export const add = (a: number, b:number) => {
return a + b
}
然後,我們在子包 pagesA
中匯入使用:
<script lang="ts">
import Vue from 'vue'
import { add } from '@/utils/common'
export default Vue.extend({
created() {
console.log(add(1, 2))
}
})
</script>
同樣,打包,然後點選開發者工具的 詳情,點選 原生程式碼-> 依賴分析
:
從上圖可以看到,我們在 主包 中的的 vender.js
沒有找到 src/utils/common.ts
中的 add
方法,但在分包 pagesA
找到了。
那如果某個 js被多個分包所引用呢?
我們再建立一個分包 pagesB
,與同樣的方式在子包 pagesB
中匯入common.ts
:
<script lang="ts">
import Vue from 'vue'
import { add } from '@/utils/common'
export default Vue.extend({
created() {
console.log(add(1, 2))
}
})
</script>
同樣,打包,然後點選開發者工具的 詳情,點選 原生程式碼-> 依賴分析
:
從圖可以看到,我們在主包中的 vendor.js
可以找到我們使用的 add
方法,在分包中沒有找到對應的 vendor.js
,所以當某個 js 僅被多個分包引用時,該 js 會被打包到主包。
事例地址:https://github.com/qq44924588...
最後,我們來驗證一下第三條規則:自定義元件:若某個自定義元件僅被一個分包引用時,且未放入到分包內,編譯時會輸出提示資訊
首先,我們在主包中的 src/components
建立一個自定義元件 SayHello
,內容如下:
<template>
<view class="content">
Hello World
</view>
</template>
然後,以同樣的方式建個分包(步驟跟上面的例子一樣),在分包的中引用我們的元件 SayHello
:
<template>
<view class="content">
<SayHello />
</view>
</template>
<script lang="ts">
import Vue from 'vue'
import SayHello from '@/components/SayHello.vue'
export default Vue.extend({
components: {
SayHello
}
})
</script>
然後,編譯可以在控制檯看到提示的資訊:
那如果自定義元件被多個分包引用呢?提示應該會消失,為了嚴謹性,我們再建個分包 pagesB
以同樣姿勢引用元件,然後編譯,再檢視控制檯:
可以看到,提示資訊消失了。
至此,UniApp 官網提到分包優化具體邏輯我們都驗證過,Nice。
事例地址:https://github.com/qq44924588...
程式碼部署後可能存在的BUG沒法實時知道,事後為了解決這些BUG,花了大量的時間進行log 除錯,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug。
交流
有夢想,有乾貨,微信搜尋 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。
本文 GitHub https://github.com/qq44924588... 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。