小程序分包
某些情况下,开发者需要将小程序划分成不同的子包,在构建时打包成不同的分包,用户在使用时按需进行加载。
在构建小程序分包项目时,构建会输出一个或多个分包。每个使用分包小程序必定含有一个主包。所谓的主包,即放置默认启动页面/TabBar 页面,以及一些所有分包都需用到公共资源/JS 脚本;而分包则是根据开发者的配置进行划分。
在小程序启动时,默认会下载主包并启动主包内页面,当用户进入分包内某个页面时,客户端会把对应分包下载下来,下载完成后再进行展示。
目前小程序分包大小有以下限制:
- 整个小程序所有分包大小不超过 20M
- 单个分包/主包大小不能超过 2M
对小程序进行分包,可以优化小程序首次启动的下载时间,以及在多团队共同开发时可以更好的解耦协作。
官方所提供的文档分为如下 3 个内容:
- 使用分包
- 独立分包
- 分包预加载
所以这里不再照搬官网做介绍,详细了可以参阅官方文档:https://developers.weixin.qq.com/miniprogram/dev/framework/subpackages.html
本文我们主要来看一下分包的实际操作。
这里以【applet-subcontracting】项目为例。
根据官网的介绍,分包主要是将小程序的页面进行分门别类,例如:
├── app.js
├── app.json
├── app.wxss
├── packageA
│ └── pages
│ ├── cat
│ └── dog
├── packageB
│ └── pages
│ ├── apple
│ └── banana
├── pages
│ ├── index
│ └── logs
└── utils
然后在 app.json 文件中使用 subpackages 字段来声明项目分包结构:
{
"pages":[
"pages/index",
"pages/logs"
],
"subpackages": [
{
"root": "packageA",
"pages": [
"pages/cat",
"pages/dog"
]
}, {
"root": "packageB",
"name": "pack2",
"pages": [
"pages/apple",
"pages/banana"
]
}
]
}
subpackages 字段对应的值为一个数组,数组里面记录了分几个包,每个包对应一个对象,对象可以设置如下的属性值。如下:
来看【applet-subcontracting】项目实际的操作示例。
首先是我们的项目目录,以前我们所有的页面,都是放在 pages 目录下面的。现在要进行分包的话,虽然也都是放在 pages 目录下,但是 pages 目录下面又分为了 package1、package2 和 package3。
这里我们其实就是分成了 3 个包,每个包有自己的目录,展开后如下图所示:
接下来我们就需要在 app.json 里面进行配置了。配置代码片段如下:
{
"pages":[
"pages/package1/pages/index/index",
"pages/package1/pages/cat/cat",
"pages/package1/pages/dog/dog",
"pages/package1/pages/apple/apple",
"pages/package1/pages/banana/banana"
],
"subpackages": [
{
"root": "pages/package2",
"name": "pack2",
"pages": [
"pages/cat/cat",
"pages/dog/dog"
]
}, {
"root": "pages/package3",
"name": "pack3",
"pages": [
"pages/apple/apple",
"pages/banana/banana"
]
}
],
// ...
}
可以看到,pages 里面配置第一次要加载的页面,这里我们加载的是 package1 里面的所有页面。
而 package2 和 package3 则采取的是分包的形式,被写入到了 subpackages 里面。
在开发工具的详情中,可以看到当前的分包情况,如下图所示:
独立分包
独立分包就是这个包是独立的,不依赖于主包就能用,当设置为独立分包时,我们从独立分包进入 “不会加载主包”,只有进入主包页面或者非独立分包页面是才加载主包。
使用的方法也很简单,只需要在配置包的时候,把 independent 设置为 true 就会成为独立分包。
例如:
{
// ...
"subpackages": [{
"root": "pages/package2",
"name": "pack2",
"pages": [
"pages/cat/cat",
"pages/dog/dog"
],
"independent": true
}, {
"root": "pages/package3",
"name": "pack3",
"pages": [
"pages/apple/apple",
"pages/banana/banana"
]
}],
// ...
}
在上面的代码中,我们将 pack2 设置为了独立分包。
独立分包注意事项:
-
从独立分包进入的时候,由于没有加载主包,因此通过 getApp 方法拿到的是 undefined。只有在加载主包回来这个页面以后才能通过 getApp 拿到全局参数 ⚠️。
-
独立分包不能共享其他包样式,包括 app.wxss 样式 ⚠️。
-
独立分包不支持使用插件 ⚠️
-
在低于 6.7.2 的微信版本的小程序独立分包当成普通分包对待,不具备独立分包的能力 ⚠️。
为了兼容独立分包进入无法全局管理变量的能力,官方在基础版本库 2.4.4 以后做了兼容,使用 getApp({allowDefault: true}) 可以预先写入变量,当主包加载的时候会同步到 app 里面 ⚠️。
const app = getApp({allowDefault: true});
app.name = "CoderJoon"; // 等主包加载的时候会同步进去
分包预加载
所谓分包预加载,就是在进入小程序某个页面时,由框架自动预下载可能需要的分包,提升进入后续分包页面时的启动速度。这就需要你去判断了 预判用户的下一步操作 提前进行预加载!
例如:
{
// 注意 这里的packages 可以写为 subpackages 中起的name 作为别名
"preloadRule": {
//进入 "pages/package1/pages/cat/cat" 然后预加载 pack2
"pages/package1/pages/cat/cat": {
"network": "all",
"packages": ["pack2"]
},
"pages/package1/pages/apple/apple": {
//进入 "pages/package1/pages/apple/apple" 然后预加载 pack3
"network": "all",
"packages": ["pack3"]
}
},
// ...
}
在上面的配置中,表明进入 cat 页面时,就加载 pack2 这个包,进入 apple 这个页面时,就加载 pack3 这个包。
而 network 对应的 all 代表在指定网络下预下载,可选值有 all(不限网络)和 wifi(仅 wifi 下预下载)。
分包异步化(建议看看官方文档 很详细!)
在小程序中,不同的分包对应不同的下载单元。
不同的包之间无法相互使用自定义组件或者 require。
subpackA // 我们在subpackA中自定义了 item 组件
subpackB // 在这里你就不能用 item 组件
这样就很鸡肋 我写组件的目的就是为了 复用 现在不让我用了 我很烦 这时候我们就可以使用 分包异步化 来复用组件了
跨分包自定义组件引用(占位渲染)
有点类似于骨架屏,先用内置组件或者本包中的组件进行一个占位渲染,之后在其他包加载之后再渲染为对应的组件。
要使用此特性,直接在当前包对应的 json 文件中进行配置即可:
{
"componentPlaceholder": { //配置您的占位组件
"button": "view",
"list": "simple-list"
}
}
跨分包 JS 代码引用
在当前包如果要使用其他包的代码,首先通过 require 来引入,然后注意这个过程是异步的。