百度智能小程序 加速initData的生成
合理使用分包
基础库 3.60.2 及以上版本开始支持独立分包页面,3.170.3 及以上版本开始支持独立分包页面引用自定义组件。
Tips:在搜索结果和信息流页面,小程序底层框架将预先下载主包的逻辑与资源,请将小程序分发和重要的页面放到主包里,其它页面合理的划分到其它分包中。
结合智能小程序的启动流程,包下载与解析是整个启动过程中的一种重要阶段,该阶段耗时与小程序页面所属包大小呈正相关,将直接影响到 initData 完成收集的时间,从而影响首屏渲染。
因此,可以采用分包相关技术:普通分包、独立分包、分包预下载,来优化包处理的几个关键阶段,以减小 initData 的准备时间,最大程度提前首屏渲染起始点。
下述案例对比了未使用分包、使用普通分包、使用独立分包三种不同方式的资源下载耗时(实际可能受网络影响,但耗时趋势一致)。
接下来,我们将介绍使用分包将带来的优势。
减小包下载时间
我们以某个小程序为例,在未分包、普通分包和独立分包的情况下,小程序包下载流程如下:
从上图可以了解小程序包下载流程大致过程,总结为:
- 如果没有分包,首次启动将下载小程序完整包;
- 首次启动普通分包中的页面时,宿主客户端将会下载主包和该页面分包资源;
- 首次启动独立分包中的页面时,宿主客户端只下载该页面分包资源。
当清楚小程序包下载过程之后,我们可以将页面进行合理的分包,然后最大程度节省当前页面所属包的下载时间。
当小程序发布时,小程序的业务代码将被打包在一起,在小程序启动时一次性下载完成。如果使用分包策略,小程序的代码将会被划分为一个主包(包含小程序启动时会马上打开的页面代码和相关资源)和其余分包(包含分包页面的代码和资源)。
当启动小程序时(假设打开页面在主包内),则主包下载完成后将会立即启动小程序,节省其它分包代码的加载时间。
例子:
假设有一个资讯类小程序,其中最主要的页面是主页和资讯详情页,可以使用分包策略,将主页和资讯详情页划分到主包,其它页面(工具页和非主要页面)合理划分到其它分包,当启动主页或者资讯详情页时,宿主App将只下载主包,随后立即开始逻辑加载。
减小包执行时间
当下载完小程序包之后,其逻辑代码会被加载到适当的线程中执行,执行过程中将会调用基础库底层接口完成初始化工作。
从以下图可以看出三种分包情况下,页面注册与初始化工作耗时情况:
具体工作如下:
- 如果没有使用分包,将进行以下工作:
- 执行所有页面 JS 文件及其依赖所有文件;
- 注册所有页面,调用所有页面的 Page 构造器方法,来记录页面的基础信息(包括初始数据、方法,以及其它的合成过程);
- 所有页面需要的其它初始化工作。
在此过程中,我们不难看出,除某些高频可能被随即打开的页面,其它页面的逻辑加载执行都是比较浪费启动过程资源的。
- 如果合理使用分包,在启动过程将只会执行该页面所属包的相关逻辑:
- 执行该页面所属包中的 JS 文件及其依赖文件;
- 注册该包中的页面,调用该包中页面的 Page 构造器方法,来记录页面的基础信息(包括初始数据、方法,以及其它的合成过程);
- 包中页面需要的其它初始化工作。
从以上执行流程,我们可以了解到合理使用分包将会最大程度减小初始化时间。
分包预下载
在使用分包加载后,虽然能够显著提升小程序的启动速度,但是当跳转到其它分包页面时,需要等待该分包下载完成后才能打开页面,将会造成页面切换的延迟,影响小程序的使用体验。
分包预下载(swan.loadSubPackage)可以解决首次进入分包页面带来的延迟问题。使用之后,在用户进入分包页面之前就预先将分包下载完成,当用户进入分包页面时就能够更快的启动页面。
以下为分包预下载过程:
开发者可以预先配置某个页面可能会跳转到的分包(当启动页面为独立分包页面时,也可以预下载主包),在进入小程序某个页面时,由基础库在后台自动预下载可能需要的分包。用户在进行页面跳转时,该分包通常已经下载完成,无需额外等待,可以有效提升进入后续分包页面时的启动速度。
合理使用动态库
动态库,是指可被添加到小程序内直接使用的功能组件。开发者可直接在小程序内使用动态库,无需重复开发,为用户提供更丰富的服务。具体动态库使用请参考动态库的使用。
加载流程与原理
我们从 智能小程序的启动流程 章节可以了解到,动态库的独立资源将在逻辑和渲染层分别进行加载,在此过程中将会加载动态库的全部代码(逻辑和样式),然后解析执行,但实际上引用的动态库中往往包含大量未使用的逻辑,导致加载过程中大量资源的浪费,从而阻塞 initData 的收集时间,进而直接影响到页面渲染。
针对于此,我们提出以下使用建议:
- 充分了解所使用的动态库功能,如果只需要少部分功能,则不必引用其庞大的动态库拖慢整个加载过程,可以选择在小程序中编写功能逻辑;
- 正确引用动态库中的自定义组件,参考 合理使用自定义组件。
合理使用 App.onLaunch
App.onLaunch是进入小程序的第一个生命周期函数,很多开发者会在App.onLaunch中执行一些初始化操作。如果使用不当,会显著影响首屏显示速度。
使用建议
- 避免在 App.onLaunch 中执行耗时很长的任务。有可能的话,将任务推移到页面显示完成后执行。
- 减少、避免在 App.onLaunch 中调用一些同步 API。使用异步 API 代替同步,并尽量减少、延后首页面显示非必需的 API 调用。
- 将 App.onLaunch 中的页面请求放在 Page.onInit 生命周期中:一些开发者为了提前首页面网络请求,会将数据请求代码放到 App.onLaunch 中执行;高版本的基础库提供了 Page.onInit,如果 App.onLaunch 耗时较短,则可以认为将页面网络请求放在自身的 Page.onInit 中,效果与 App.onLaunch 近似。
示例
App({
onLaunch: function () {
const key = 'app-launch-id';
// 模拟长任务
let count = 3000;
while (count--) {
const value = swan.getStorageSync(key);
swan.getStorageSync(key, value ? +value : 1);
}
}
});
从下图可以明显地看出,App.onLaunch 的耗时越长,首页面白屏的时间越长。
长耗时的 App.onLaunch(count = 3000)
短耗时的 App.onLaunch(count = 300)
更多建议: