微信小程序分包
介绍
微信小程序对打包上传有大小限制,当代码包大于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
| { "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
|
require('../subPackageB/utils.js', utils => { console.log(utils.whoami) }, ({mod, errMsg}) => { console.error(`path: ${mod}, ${errMsg}`) })
require.async('../commonPackage/index.js').then(pkg => { pkg.getPackageName() }).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}`) })
requirePlugin.async('live-player-plugin').then(livePlayer => { console.log(livePlayer.getPluginVersion()) }).catch(({mod, errMsg}) => { console.error(`path: ${mod}, ${errMsg}`) })
|
跳转
需在配置的 pages 路径前加上分包名以跳转。
参考资料
微信官方文档 使用分包
关于本人
HaiYao的博客
Git主页