手把手教你小程序分包

891 阅读4分钟

小程序分包

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的生命周期

当从独立分包启动小程序时,主包中 ApponLaunch 和首次 onShow 会在从独立分包页面首次进入主包或其他普通分包页面时调用。

由于独立分包中无法定义 App,小程序生命周期的监听可以使用 wx.onAppShowwx.onAppHide 完成。App 上的其他事件可以使用 wx.onErrorwx.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上