有梦想,有干货,微信搜索 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。
本文 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... 已收录,有一线大厂面试完整考点、资料以及我的系列文章。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。