2023-02-21 22:34:08 +08:00

249 lines
7.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 小程序分包
某些情况下,开发者需要将小程序划分成不同的子包,在构建时打包成不同的分包,用户在使用时按需进行加载。
在构建小程序分包项目时,构建会输出一个或多个分包。每个使用分包小程序必定含有一个主包。所谓的主包,即放置默认启动页面/*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* 字段对应的值为一个数组,数组里面记录了分几个包,每个包对应一个对象,对象可以设置如下的属性值。如下:
![image-20230214085459929](https://xiejie-typora.oss-cn-chengdu.aliyuncs.com/2023-02-14-005500.png)
来看【*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*-