codecamp

百度智能小程序 加速initData的生成

合理使用分包

基础库 3.60.2 及以上版本开始支持独立分包页面,3.170.3 及以上版本开始支持独立分包页面引用自定义组件。

Tips:在搜索结果和信息流页面,小程序底层框架将预先下载主包的逻辑与资源,请将小程序分发和重要的页面放到主包里,其它页面合理的划分到其它分包中。


结合智能小程序的启动流程,包下载与解析是整个启动过程中的一种重要阶段,该阶段耗时与小程序页面所属包大小呈正相关,将直接影响到 initData 完成收集的时间,从而影响首屏渲染。

因此,可以采用分包相关技术:普通分包独立分包分包预下载,来优化包处理的几个关键阶段,以减小 initData 的准备时间,最大程度提前首屏渲染起始点。

下述案例对比了未使用分包、使用普通分包、使用独立分包三种不同方式的资源下载耗时(实际可能受网络影响,但耗时趋势一致)。

接下来,我们将介绍使用分包将带来的优势。

减小包下载时间

我们以某个小程序为例,在未分包、普通分包和独立分包的情况下,小程序包下载流程如下:

从上图可以了解小程序包下载流程大致过程,总结为:

  1. 如果没有分包,首次启动将下载小程序完整包;
  2. 首次启动普通分包中的页面时,宿主客户端将会下载主包和该页面分包资源;
  3. 首次启动独立分包中的页面时,宿主客户端只下载该页面分包资源。

当清楚小程序包下载过程之后,我们可以将页面进行合理的分包,然后最大程度节省当前页面所属包的下载时间。

当小程序发布时,小程序的业务代码将被打包在一起,在小程序启动时一次性下载完成。如果使用分包策略,小程序的代码将会被划分为一个主包(包含小程序启动时会马上打开的页面代码和相关资源)和其余分包(包含分包页面的代码和资源)。

当启动小程序时(假设打开页面在主包内),则主包下载完成后将会立即启动小程序,节省其它分包代码的加载时间。

例子:

假设有一个资讯类小程序,其中最主要的页面是主页和资讯详情页,可以使用分包策略,将主页和资讯详情页划分到主包,其它页面(工具页和非主要页面)合理划分到其它分包,当启动主页或者资讯详情页时,宿主App将只下载主包,随后立即开始逻辑加载。

减小包执行时间

当下载完小程序包之后,其逻辑代码会被加载到适当的线程中执行,执行过程中将会调用基础库底层接口完成初始化工作。

从以下图可以看出三种分包情况下,页面注册与初始化工作耗时情况:

具体工作如下:

  • 如果没有使用分包,将进行以下工作:
    • 执行所有页面 JS 文件及其依赖所有文件;
    • 注册所有页面,调用所有页面的 Page 构造器方法,来记录页面的基础信息(包括初始数据、方法,以及其它的合成过程);
    • 所有页面需要的其它初始化工作。

在此过程中,我们不难看出,除某些高频可能被随即打开的页面,其它页面的逻辑加载执行都是比较浪费启动过程资源的。

  • 如果合理使用分包,在启动过程将只会执行该页面所属包的相关逻辑:
    • 执行该页面所属包中的 JS 文件及其依赖文件;
    • 注册该包中的页面,调用该包中页面的 Page 构造器方法,来记录页面的基础信息(包括初始数据、方法,以及其它的合成过程);
    • 包中页面需要的其它初始化工作。

从以上执行流程,我们可以了解到合理使用分包将会最大程度减小初始化时间。

分包预下载

在使用分包加载后,虽然能够显著提升小程序的启动速度,但是当跳转到其它分包页面时,需要等待该分包下载完成后才能打开页面,将会造成页面切换的延迟,影响小程序的使用体验。

分包预下载(swan.loadSubPackage)可以解决首次进入分包页面带来的延迟问题。使用之后,在用户进入分包页面之前就预先将分包下载完成,当用户进入分包页面时就能够更快的启动页面。

以下为分包预下载过程:

开发者可以预先配置某个页面可能会跳转到的分包(当启动页面为独立分包页面时,也可以预下载主包),在进入小程序某个页面时,由基础库在后台自动预下载可能需要的分包。用户在进行页面跳转时,该分包通常已经下载完成,无需额外等待,可以有效提升进入后续分包页面时的启动速度。



合理使用动态库

动态库,是指可被添加到小程序内直接使用的功能组件。开发者可直接在小程序内使用动态库,无需重复开发,为用户提供更丰富的服务。具体动态库使用请参考动态库的使用

加载流程与原理

我们从 智能小程序的启动流程 章节可以了解到,动态库的独立资源将在逻辑和渲染层分别进行加载,在此过程中将会加载动态库的全部代码(逻辑和样式),然后解析执行,但实际上引用的动态库中往往包含大量未使用的逻辑,导致加载过程中大量资源的浪费,从而阻塞 initData 的收集时间,进而直接影响到页面渲染。

针对于此,我们提出以下使用建议:

  • 充分了解所使用的动态库功能,如果只需要少部分功能,则不必引用其庞大的动态库拖慢整个加载过程,可以选择在小程序中编写功能逻辑;
  • 正确引用动态库中的自定义组件,参考 合理使用自定义组件


合理使用 App.onLaunch

App.onLaunch是进入小程序的第一个生命周期函数,很多开发者会在App.onLaunch中执行一些初始化操作。如果使用不当,会显著影响首屏显示速度。

使用建议

  1. 避免在 App.onLaunch 中执行耗时很长的任务。有可能的话,将任务推移到页面显示完成后执行。
  2. 减少、避免在 App.onLaunch 中调用一些同步 API。使用异步 API 代替同步,并尽量减少、延后首页面显示非必需的 API 调用。
  3. 将 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)


百度智能小程序 智能小程序的启动流程
百度智能小程序 提前请求主数据
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

百度智能小程序开发文档

百度智能小程序 组件

百度智能小程序 地图

百度智能小程序 画布

百度智能小程序 API

百度智能小程序 界面

百度智能小程序 关注小程序引导组件

百度智能小程序 自定义组件

百度智能小程序 媒体

百度智能小程序 设备

百度智能小程序 拨打电话

百度智能小程序 内存警报

百度智能小程序 手机联系人

百度智能小程序 用户截屏事件

百度智能小程序 第三方平台

百度智能小程序 开放接口

百度智能小程序 百度收银支付

百度智能小程序 分包预下载

百度智能小程序 数据分析

百度智能小程序 服务端

百度智能小程序 云开发

百度智能小程序 初始化

百度智能小程序 云函数

百度智能小程序 服务端初始化

百度智能小程序 服务器获取上下文

百度智能小程序 服务端云函数

百度智能小程序 开发教程

百度智能小程序 功能开发

百度智能小程序 基本原理

百度智能小程序 小程序自动化

百度智能小程序 视频教程

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }