小程序分包
1.为什么要分包
小程序本是作为轻量级应用,为了兼顾其敏捷轻便性,限制主宝加分包的大小不超过20M,其中每个包的大小不超过2M;
依据:按照功能不同划分,可以按需下载。
优点:可以缩短小程序首次启用的下载时间;
方便解耦协作;
2.分包配置
关键字:subpackages
1.app.json中增加
subpackages": [
{
"root": "packageA",
"pages": [
"pages/cat",
"pages/dog"
]
}, {
"root": "packageB",
"name": "pack2",
"pages": [
"pages/apple",
"pages/banana"
]
}
]
2.路径更改,如果以前已经新增了对应的文件和组件,需要将他们迁移到新路径中;原有的组件的引用也需要修改为对应的路径;
3.tabBar的文件必须放在主包里面;
4.分包A可以require主包的内容,不能require分包B的内容(分包异步化除外);
5.在新客户端使用分包,在老客户端还是使用完整包。
3.独立分包-可以独立于主包和其他分包运行
特性:从独立分包中页面进入小程序时,不需要下载主包。
当用户进入普通分包或主包内页面时,主包才会被下载。
优势:独立分包不依赖主包即可运行,可以大幅提升分包页面的启动速度。
关键字:independent
"subpackages": [
{
"root": "moduleB",
"pages": [
"pages/pear",
"pages/pineapple"
],
"independent": true
}
]
注意:
1.独立分包中不能依赖主包和其他分包中的内容(wxss,js,自定义组件) 分包异步化时除外
2.独立分包中不能定义app。
3.独立分包中暂时不支持使用插件。
4.getApp()
1)从主包到独立分包:主包已存在,app已存在,getApp() 可以获取到真正的 App。
2)从独立分包到主包:主包不存在,App也不存在,此时调用 getApp() 获取到的是 undefined。
开发者无法通过 App 对象实现独立分包和小程序其他部分的全局变量共享。
在独立分包中可通过allowDefault:true
//独立分包中
const app = getApp({allowDefault: true}) // {}
app.data = 456
app.global = {}
//app.js中
App({
data: 123,
other: 'hello'
})
console.log(getApp()) // {global: {}, data: 456, other: 'hello'}
5.App的生命周期
当从独立分包启动小程序时,主包中 App 的 onLaunch 和首次 onShow 会在从独立分包页面首次进入主包或其他普通分包页面时调用。
由于独立分包中无法定义 App,小程序生命周期的监听可以使用 wx.onAppShow,wx.onAppHide 完成。App 上的其他事件可以使用 wx.onError,wx.onPageNotFound 监听。
6.独立分包版本^6.7.2,否则以普通分包处理。
3.分包预加载
在进入小程序某个页面时,由框架自动预下载可能需要的分包,提升进入后续分包页面时的启动速度。
关键字:preloadRule
"subpackages":[
{
"root": "packageA",
"name": "packageA",
"pages": [
"pages/index/index",
],
"independent":false
}
],
"preloadRule":{
"pages/buy/index":{
"network":"all", //'all'不限网络 ’wifi‘仅在wifi下预加载
"packages":["configurationMajor"]
}
},
注意:
1.同一个分包中的页面享有共同的预下载大小限额 2M,限额会在工具中打包时校验。
2.基础库 2.3.0 开始支持,低版本需做兼容处理。
4.分包异步化
为什么要分包异步化
让非独立分包可以依赖主包外,还可以让分包之间能互相使用自定义组件或进行 require。
1.占位组件-跨分包自定义组件引用
一个分包使用其他分包的自定义组件时,由于其他分包还未下载或注入,其他分包的组件处于不可用的状态。
用渲染占位组件进行替换,当分包加载完成后再做替换。
{
"usingComponents": {
"main-rights": "../../packageA/pages/components/rights/index",
},
"componentPlaceholder": {
"main-rights":"view"
},
}
2.跨分包 JS 代码引用-异步获取引用
// 使用回调函数风格的调用
require('../subPackageB/utils.js', utils => {
console.log(utils.whoami) // Wechat MiniProgram
}, ({mod, errMsg}) => {
console.error(`path: ${mod}, ${errMsg}`)
})
// 或者使用 Promise 风格的调用
let initFunction
require.async('../../subPackageB/pages/utils').then(pkg => {
initFunction = pkg.initFunction
})
可能会发生分包未预下载完便进入页面的情况,可以对该函数进行判断
if (!initFunction) {
require('../../subPackageB/pages/utils', pkg => {
initFunction = pkg.initFunction
//后续的操作
})
}
插件也可以用该方法
// 使用回调函数风格的调用
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}`)
})
5.分包可能造成的问题及对应解决方式
所有跟路径有关的报错(80%),首先看相对路径是否已经是分包后的最新路径
1.组件未在对应路径中找到
报错:Component is not found in path “xxxxx” (using by “xxxx”)
解决方式:组件是否调用异步,需要占位。
"componentPlaceholder": {
"c-rights":"view"
},
2.js文件函数未定义
报错:module 'packageA/pages/util/index.js' is not defined, require args is '../../packageA/pages/ util/index'
解决方式:是否引用了分包中的函数,有无预加载,能否正常调用
let functionA, functionB, functionC
require('../../packageA/pages/_util/index', utils => {
functionA = utils.functionA
functionB = utils.functionB
functionC = utils.functionC
})
3.基础库版本太低
报错:require.async is not a function
解决方式:升级基础库版本至2.17.3上