250 lines
7.2 KiB
Markdown
250 lines
7.2 KiB
Markdown
# 小程序分包
|
||
|
||
某些情况下,开发者需要将小程序划分成不同的子包,在构建时打包成不同的分包,用户在使用时按需进行加载。
|
||
|
||
在构建小程序分包项目时,构建会输出一个或多个分包。每个使用分包小程序必定含有一个主包。所谓的主包,即放置默认启动页面/*TabBar* 页面,以及一些所有分包都需用到公共资源/*JS* 脚本;而分包则是根据开发者的配置进行划分。
|
||
|
||
在小程序启动时,默认会下载主包并启动主包内页面,当用户进入分包内某个页面时,客户端会把对应分包下载下来,下载完成后再进行展示。
|
||
|
||
目前小程序分包大小有以下限制:
|
||
|
||
- 整个小程序所有分包大小不超过 *20M*
|
||
- 单个分包/主包大小不能超过 *2M*
|
||
|
||
对小程序进行分包,可以优化小程序首次启动的下载时间,以及在多团队共同开发时可以更好的解耦协作。
|
||
|
||
官方所提供的文档分为如下 *3* 个内容:
|
||
|
||
- 使用分包
|
||
- 独立分包
|
||
- 分包预加载
|
||
|
||
所以这里不再照搬官网做介绍,详细了可以参阅官方文档:*https://developers.weixin.qq.com/miniprogram/dev/framework/subpackages.html*
|
||
|
||
本文我们主要来看一下分包的实际操作。
|
||
|
||
这里以【*applet-subcontracting*】项目为例。
|
||
|
||
根据官网的介绍,分包主要是将小程序的页面进行分门别类,例如:
|
||
|
||
```js
|
||
├── app.js
|
||
├── app.json
|
||
├── app.wxss
|
||
├── packageA
|
||
│ └── pages
|
||
│ ├── cat
|
||
│ └── dog
|
||
├── packageB
|
||
│ └── pages
|
||
│ ├── apple
|
||
│ └── banana
|
||
├── pages
|
||
│ ├── index
|
||
│ └── logs
|
||
└── utils
|
||
```
|
||
|
||
然后在 *app.json* 文件中使用 *subpackages* 字段来声明项目分包结构:
|
||
|
||
```js
|
||
{
|
||
"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*】项目实际的操作示例。
|
||
|
||
<img src="https://xiejie-typora.oss-cn-chengdu.aliyuncs.com/2023-02-14-005516.png" alt="image-20230214085516276" style="zoom: 80%;" />
|
||
|
||
首先是我们的项目目录,以前我们所有的页面,都是放在 *pages* 目录下面的。现在要进行分包的话,虽然也都是放在 *pages* 目录下,但是 *pages* 目录下面又分为了 *package1、package2* 和 *package3*。
|
||
|
||
这里我们其实就是分成了 *3* 个包,每个包有自己的目录,展开后如下图所示:
|
||
|
||
<img src="https://xiejie-typora.oss-cn-chengdu.aliyuncs.com/2023-02-14-005544.png" alt="image-20230214085544467" style="zoom:80%;" />
|
||
|
||
接下来我们就需要在 *app.json* 里面进行配置了。配置代码片段如下:
|
||
|
||
```js
|
||
{
|
||
"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* 里面。
|
||
|
||
在开发工具的详情中,可以看到当前的分包情况,如下图所示:
|
||
|
||
<img src="https://xiejie-typora.oss-cn-chengdu.aliyuncs.com/2023-02-14-005619.png" alt="image-20230214085619380" style="zoom: 50%;" />
|
||
|
||
### 独立分包
|
||
|
||
独立分包就是这个包是独立的,不依赖于主包就能用,当设置为独立分包时,我们从独立分包进入不会加载主包,只有进入主包页面或者非独立分包页面是才加载主包。
|
||
|
||
使用的方法也很简单,只需要在配置包的时候,把 *independent* 设置为 *true* 就会成为独立分包。
|
||
|
||
例如:
|
||
|
||
```js
|
||
{
|
||
// ...
|
||
"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* 里面。
|
||
|
||
```js
|
||
const app = getApp({allowDefault: true});
|
||
|
||
app.aa = 1; // 等主包加载的时候会同步进去
|
||
```
|
||
|
||
### 分包预加载
|
||
|
||
所谓分包预加载,就是在进入小程序某个页面时,由框架自动预下载可能需要的分包,提升进入后续分包页面时的启动速度。
|
||
|
||
例如:
|
||
|
||
```js
|
||
{
|
||
// ...
|
||
"preloadRule": {
|
||
"pages/package1/pages/cat/cat": {
|
||
"network": "all",
|
||
"packages": ["pack2"]
|
||
},
|
||
"pages/package1/pages/apple/apple": {
|
||
"network": "all",
|
||
"packages": ["pack3"]
|
||
}
|
||
},
|
||
// ...
|
||
}
|
||
```
|
||
|
||
在上面的配置中,表明进入 *cat* 页面时,就加载 *pack2* 这个包,进入 *apple* 这个页面时,就加载 *pack3* 这个包。
|
||
|
||
而 *network* 对应的 *all* 代表在指定网络下预下载,可选值有 *all*(不限网络)和 *wifi*(仅 *wifi* 下预下载)。
|
||
|
||
|
||
|
||
## 分包异步化
|
||
|
||
在小程序中,不同的分包**对应不同的下载单元**。
|
||
|
||
不同的包之间无法相互使用自定义组件或者 require。
|
||
|
||
```js
|
||
subpackA
|
||
item 自定义组件
|
||
subpackB
|
||
```
|
||
|
||
|
||
|
||
**跨分包自定义组件引用(占位渲染)**
|
||
|
||
有点类似于骨架屏,先用内置组件或者本包中的组件进行一个占位渲染,之后在其他包加载之后再渲染为对应的组件。
|
||
|
||
要使用此特性,直接在当前包对应的 json 文件中进行配置即可:
|
||
|
||
```js
|
||
{
|
||
"componentPlaceholder": {
|
||
"button": "view",
|
||
"list": "simple-list"
|
||
}
|
||
}
|
||
```
|
||
|
||
|
||
|
||
**跨分包 JS 代码引用**
|
||
|
||
在当前包如果要使用其他包的代码,首先通过 require 来引入,然后注意这个过程是异步的。
|
||
|
||
|
||
|
||
-*EOF*-
|
||
|
||
|