Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

微信小程序分包

介绍

微信小程序对打包上传有大小限制,当代码包大于2MB时无法上传,需要对小程序进行分包。
关于分包还有以下限制:

  • 每个使用分包小程序必定含有一个主包。
  • 单个分包/主包大小不能超过 2M。
  • 整个小程序所有分包大小不超过 30M。
  • 声明 subPackages 后,将按 subPackages 配置路径进行打包,subPackages 配置路径外的目录将被打包到主包中。
  • 主包也可以有自己的 pages,即最外层的 pages 字段。
  • subPackages 的根目录不能是另外一个 subPackages 内的子目录。
  • tabBar 页面必须在主包内。
  • 分包无法 require 其他分包 JS 文件,但可以 require 主包、本身内的 JS 文件;使用 分包异步化 时不受此条限制。
  • 分包无法 import 其他分包的 template,但可以 require 主包、本身内的 template。
  • 分包无法使用其他分包的资源,但可以使用主包、本身内的资源。

所谓的主包,即放置默认启动页面/TabBar 页面,以及一些所有分包都需用到公共资源/JS 脚本;分包则是根据配置进行划分。

在小程序启动时,默认会下载主包并启动主包内页面,当用户进入分包内某个页面时,客户端会把对应分包下载下来,下载完成后再进行展示。

分包配置

在配置文件中使用 subPackages 关键字进行分包。
subPackages 关键字与 pages 关键字在同一目录。
以下是 subPackages 的一些配置项

字段 类型 说明
root String 分包根目录
name String 分包别名,分包预下载时可以使用
pages StringArray 分包页面路径,相对于分包根目录
independent Boolean 分包是否是独立分包
entry String 分包入口文件

来自管网的例子
分包配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 分包配置
├── app.js
├── app.json
├── app.wxss
├── packageA
│ └── pages
│ ├── cat
│ └── dog
├── packageB
│ └── pages
│ ├── apple
│ └── banana
├── pages
│ ├── index
│ └── logs
└── utils

分包配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 分包配置
{
"pages":[
"pages/index",
"pages/logs"
],
"subPackages": [
{
"root": "packageA",
"pages": [
"pages/cat",
"pages/dog"
],
"entry": "index.js"
}, {
"root": "packageB",
"name": "pack2",
"pages": [
"pages/apple",
"pages/banana"
]
}
]
}

独立分包

可以独立于主包和其他分包运行。从独立分包中页面进入小程序时,不需要下载主包。当用户进入普通分包或主包内页面时,主包才会被下载。
在配置分包时配置项 independent 设置为 true,即可设置为独立分包。

其有以下特性

  • 独立分包不依赖主包即可运行,可以很大程度上提升分包页面的启动速度。
  • 一个小程序中可以有多个独立分包。
  • 独立分包中不能依赖主包和其他分包中的内容。
  • 主包中的 app.wxss 对独立分包无效,应避免在独立分包页面中使用 app.wxss 中的样式。
  • 独立分包中暂时不支持使用插件。

分包预下载

在进入小程序某个页面时,由框架自动预下载可能需要的分包,提升进入后续分包页面时的启动速度。对于独立分包,也可以预下载主包。
通过在 app.json 增加 preloadRule 配置来控制。

preloadRule 中,key 是页面路径,value 是进入此页面的预下载配置,每个配置有以下几项:

字段 类型 必填 默认值 说明
packages StringArray 进入页面后预下载分包的 root 或 name。__APP__ 表示主包。
network String wifi 在指定网络下预下载,可选值为:
all: 不限网络
wifi: 仅wifi下预下载

管网例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
{
"pages": ["pages/index"],
"subpackages": [
{
"root": "important",
"pages": ["index"],
},
{
"root": "sub1",
"pages": ["index"],
},
{
"name": "hello",
"root": "path/to",
"pages": ["index"]
},
{
"root": "sub3",
"pages": ["index"]
},
{
"root": "indep",
"pages": ["index"],
"independent": true
}
],
"preloadRule": {
"pages/index": {
"network": "all",
"packages": ["important"]
},
"sub1/index": {
"packages": ["hello", "sub3"]
},
"sub3/index": {
"packages": ["path/to"]
},
"indep/index": {
"packages": ["__APP__"]
}
}
}

跨分包引用

组件

一个分包使用其他分包的自定义组件时,由于其他分包还未下载或注入,其他分包的组件处于不可用的状态。通过为其他分包的自定义组件设置 占位组件,我们可以先渲染占位组件作为替代,在分包下载完成后再进行替换。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// subPackageA/pages/index.json
{
"usingComponents": {
"button": "../../commonPackage/components/button",
"list": "../../subPackageB/components/full-list",
"simple-list": "../components/simple-list",
"plugin-comp": "plugin://pluginInSubPackageB/comp"
},
"componentPlaceholder": {
"button": "view",
"list": "simple-list",
"plugin-comp": "view"
}
}

button 和 list 两个自定义组件是跨分包引用组件,其中 button 在渲染时会使用内置组件 view 作为替代,list 会使用当前分包内的自定义组件 simple-list 作为替代进行渲染;在这两个分包下载完成后,占位组件就会被替换为对应的跨分包组件。

JS

一个分包中的代码引用其它分包的代码时,为了不让下载阻塞代码运行,我们需要异步获取引用的结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
// subPackageA/index.js
// 使用回调函数风格的调用
require('../subPackageB/utils.js', utils => {
console.log(utils.whoami) // Wechat MiniProgram
}, ({mod, errMsg}) => {
console.error(`path: ${mod}, ${errMsg}`)
})
// 或者使用 Promise 风格的调用
require.async('../commonPackage/index.js').then(pkg => {
pkg.getPackageName() // 'common'
}).catch(({mod, errMsg}) => {
console.error(`path: ${mod}, ${errMsg}`)
})

插件

1
2
3
4
5
6
7
8
9
10
11
12
// 使用回调函数风格的调用
requirePlugin('live-player-plugin', livePlayer => {
console.log(livePlayer.getPluginVersion())
}, ({mod, errMsg}) => {
console.error(`path: ${mod}, ${errMsg}`)
})
// 或者使用 Promise 风格的调用
requirePlugin.async('live-player-plugin').then(livePlayer => {
console.log(livePlayer.getPluginVersion())
}).catch(({mod, errMsg}) => {
console.error(`path: ${mod}, ${errMsg}`)
})

跳转

需在配置的 pages 路径前加上分包名以跳转。

参考资料

微信官方文档 使用分包

关于本人

HaiYao的博客
Git主页

评论