目前小程序分包大小有以下限制:
- 整个小程序所有分包大小不超过 20M
- 单个分包/主包大小不能超过 2M
随着项目的不断迭代,小程序的主包会越来越大, 终究会有一天会超过 2M
的主包限制,首先考虑到的就是图片资源放到 CDN
或者 OSS
,起初会很奏效,但是随着一些JS库的加入就没办法了,即使使用了 .min
版本,或者精简了类库代码,主包还会很大,这时候就会用到项目分包了。
使用分包
使用分包很简单,在 app.json
当中使用 subpackages
声明项目分包结构就可以。
{
"pages":[
"pages/index",
"pages/logs"
],
"subpackages": [
{
"root": "packageA", // 子包根目录
"name": "pack1", // 别名,预下载时使用
"pages": [ // 子包页面(相对于子包根目录)
"pages/cat",
"pages/dog"
]
}, {
"root": "packageB",
"name": "pack2",
"pages": [
"pages/apple",
"pages/banana"
]
}
]
}
然后只需要注意2点就好了:
subpackage
的根目录不能是另外一个subpackage
内的子目录(可以在主包目录下);tabBar
页面必须在主包内;- 不同
subpackage
间的资源无法相互引用,公共的部分可以放在主包内,或者使用 分包异步化 来解决。
有点迷糊的可以直接看官方给到的 分包加载版示例源码
独立分包
独立分包是小程序中一种特殊类型的分包,可以独立于主包和其他分包运行。
从独立分包中页面进入小程序时,不需要下载主包。当用户进入普通分包或主包内页面时,主包才会被下载。
在上边的分包基础上,给独立分包的子包增加 independent
属性既可。
{
"pages":[
"pages/index",
"pages/logs"
],
"subpackages": [
{
"root": "packageA", // 子包根目录
"name": "pack1", // 别名,可在预下载时使用
"pages": [ // 子包页面(相对于子包根目录)
"pages/cat",
"pages/dog"
]
}, {
"root": "packageB",
"name": "pack2",
"pages": [
"pages/apple",
"pages/banana"
],
"independent": true
}
]
}
限制和分包一直,并且额外的有3个条件:
- 独立分包中不能依赖主包中的内容,即不能使用公共的库和公共样式等资源;
- 在主包加载前无法使用
getApp()
; - 独立分包中暂时不支持使用插件。
这个我暂时还没有用到,具体注意事项可以查看文档 独立分包 | 微信开放文档
分包预下载
开发者可以通过配置,在进入小程序某个页面时,由框架自动预下载可能需要的分包,提升进入后续分包页面时的启动速度。对于独立分包,也可以预下载主包
预下载分包行为在 进入某个页面时触发,通过在 app.json
增加 preloadRule
项来配置。
{
"pages": [
"pages/index"
],
"subpackages": [
{
"root": "subpackage1",
"pages": [
"index"
],
},
{
"root": "subpackage2",
"name": "sub2",
"pages": [
"index"
],
},
{
"root": "subpackage3",
"name": "sub3",
"pages": [
"index"
]
},
{
"root": "indep",
"pages": [
"index"
],
"independent": true
}
],
"preloadRule": {
"pages/index": {
"network": "all", // 所有网络环境均进行预加载
"packages": ["subpackage1"] // 进入 pages/index 时加载 subpackage1 的内容
},
"subpackage1/index": {
"packages": ["sub2", "sub3"] // 进入 subpackage1/index 时加载 subpackage2 和 subpackage3 的内容
},
"indep/index": {
"network": "wifi", // 仅在wifi环境下预加载
"packages": ["__APP__"] // 进入独立分包 indep/index 时加载 主包内容
}
}
}
📍 注意:同一个分包中的页面享有共同的预下载大小限额 2M,限额会在工具中打包时校验。
如,页面 A 和 B 都在同一个分包中,A 中预下载总大小 0.5M 的分包,B中最多只能预下载总大小 1.5M 的分包。
分包异步化
在小程序中,不同的分包对应不同的下载单元;因此,除了非独立分包可以依赖主包外,分包之间不能互相使用自定义组件或进行 require
。
「分包异步化」特性将允许通过一些配置和新的接口,使部分跨分包的内容可以等待下载后异步使用,从而一定程度上解决这个限制。
✨ 可以先打开官方给的 🔗代码片段 然后对照着看。
1. 跨分包自定义组件的引用
首先是跨分包自定义组件引用,我们看示例代码当中并没有提到 分包下载
的内容,演示的代码片段中也没有,只是使用到了 占位组件 进行替代。
// subPackageA/pages/index.json
{
"usingComponents": {
"button": "../../commonPackage/components/button",
"list": "../../subPackageB/components/full-list",
"simple-list": "../components/simple-list"
},
"componentPlaceholder": {
"button": "view",
"list": "simple-list"
}
}
说明 跨分包引用自定义组件 是不需要单独处理的,小程序会自行下载使用到的跨包组件。我们只需要关注在跨包组件下载完成之前的占位和展示即可了。
2. 跨分包 JS
代码的引用
跨分包 JS
代码引用和上边的跨包组件引用不一样了,提供了专门的 async
方法 或者 使用回调的方式解决。
// subPackageA/index.js
// 使用回调函数风格的调用
require('../subPackageB/utils.js', utils => {
console.log(utils.whoami) // Wechat MiniProgram
})
// 或者使用 Promise 风格的调用
require.async('../commonPackage/index.js').then(pkg => {
pkg.getPackageName() // 'common'
})
这个就很容易理解了,需要等待代码加载完成,所以是异步操作,和跨包组件一样,这个也是自动完成的,不需要单独在外部申明。
尾声
其实小程序分包还挺简单的,就是对已经开发完成的项目再进行分包就会比较麻烦,所有的路由和资源加载路径都需要相应调整一遍。
Q1:主包使用到的分包组件是否只能放到主包内?
其实可以从 分包异步化 部分看到,并不需要把跨包调用的内容全部放到公共组件下,对于这些 自定义组件
和 JS
文件 ,我们可以直接放到子包目录下减少主包的体积,然后使用占位组件去预展示就行了,小程序会自动的加载这些内容。
Q2: 主包与分包的体积都在 1M 以内,上传时提示体积过大
不是分包过大,是分包预加载规则设定的有问题,分包设置预加载的分包超过规定大小了,
同一个分包中的页面享有共同的预下载大小限额 2M,这个限制在上边的 分包预下载 中提到了
- 问题来源:主包与分包的体积都在1M以内,上传时为什么会提示体积过大? | 微信开放社区
文档
分包加载 | 微信开放文档
独立分包 | 微信开放文档
分包预下载 | 微信开放文档
占位组件 | 微信开放文档
滴滴出行小程序体积优化实践 - 掘金