小程序启动流程介绍
在进行启动优化之前,我们先介绍一下小程序的启动过程。了解小程序的启动流程,可以帮助开发者更有针对性地选择性能优化的手段,分析性能优化的效果。
下图简要描述了部分情况下的小程序启动流程(注意:其中矩形块的高度不与对应阶段耗时成比例)。
小程序启动流程示意图(用户首次访问)
小程序启动过程主要包括以下几个环节:
1. 资源准备
1.1 小程序相关信息准备
在用户访问小程序时,传音客户端需要从传音后台获取小程序的头像、版本、配置等基本信息,以对小程序进行必要的版本管理和校验等。
为了在保证信息实时性的前提下,尽量降低对启动耗时的影响,这些信息会在本地缓存,并通过一定的机制进行更新。
信息的获取和更新需要发起网络请求。请求分为两种情况:
1) 同步请求:会阻塞小程序的启动流程,影响小程序的启动耗时。有以下情况需要进行同步请求:
- 首次访问:用户首次访问该小程序(或小程序被清理)时,客户端没有缓存,需要同步请求小程序相关信息。
2) 异步请求:与启动流程并行,不影响启动耗时。主要发生在:
- 异步更新:已使用过的小程序,则优先使用本地缓存的信息完成启动,并异步进行更新。
对启动耗时的影响
在用户首次访问小程序、缓存清理或使用长期未使用的小程序时,信息的获取和更新会影响小程序的启动耗时,耗时长短主要与网络环境有关。
这部分逻辑完全由传音客户端控制,开发者目前无法直接进行优化。
1.2 运行环境准备
小程序的运行环境包括小程序进程、客户端原生部分的系统组件和 UI 元素(如 导航栏、tabBar 等)、渲染页面使用的 WebView 容器、开发者 JavaScript 代码的运行环境、小程序基础库等等。
部分环境(如 JavaScript 引擎、小程序基础库)需要在执行小程序代码之前准备完成,其他的会在启动过程中并行进行。运行环境的准备时间相对较长(尤其是在低端设备上),会对小程序启动产生严重影响。
这部分逻辑完全由传音客户端控制,开发者目前无法直接进行优化。
1.3 代码包准备
小程序启动时,需要根据用户访问的页面,从传音后台获取代码包地址,从 CDN 下载小程序代码包,并对代码包进行校验。
为了在保证用户尽可能访问新版本的前提下,尽量降低对启动耗时的影响,小程序代码包会在本地缓存,并通过更新机制进行更新。
和相关信息准备类似,代码包下载也会有同步和异步两种情况:
1) 同步下载:会阻塞小程序的启动流程,影响小程序的启动耗时。有以下情况需要进行同步下载:
- 首次下载:用户首次访问该小程序(或小程序被清理)时,客户端没有缓存,需要同步下载代码包。
2) 异步下载:与启动流程并行,不影响启动耗时。主要发生在:
- 异步更新:对于小程序信息发生「异步更新」的情况,如果检测到小程序版本更新,会异步更新代码包。
为了降低代码包下载的耗时,我们采用了包括但不限于以下方式:
- 代码包压缩:通过对小程序代码包进行压缩,以尽可能降低下载过程中传输的数据量。
- 预先建立连接:在下载发生前,提前和 CDN 建立连接,降低下载过程中 DNS 请求和连接建立的耗时。
下载耗时是启动耗时中的重要瓶颈,在用户首次访问小程序时,代码包的下载会对启动耗时造成影响。耗时长短与网络环境,代码包压缩后大小有关。
为了保证启动速度,开发者应该尽可能的控制启动时用到的代码包大小。具体方法可以参考《代码包体积优化》。
2. 小程序代码注入(逻辑层)
小程序启动时需要从代码包内读取小程序的配置和代码,并注入到 JavaScript 引擎中。在代码注入过程中,会触发小程序的 App.onLaunch 和 Page.onLoad 生命周期。
对启动耗时的影响
小程序代码的注入耗时直接影响小程序的启动耗时。耗时长短与代码复杂度和一些复杂的计算有关。
由于「首页渲染」需要使用逻辑层发送的数据,如果小程序代码注入耗时过长,会延迟「首页渲染」开始的时间。建议开发者参考《代码注入优化》章节进行优化。
3. 小程序代码注入(视图层)
开发者的 CSS 和 DLT 会编译成 JavaScript 代码注入到视图层,包含页面渲染需要的页面结构和样式信息。
我们采用和「小程序代码注入(逻辑层)」相似的方式优化注入耗时。
对启动耗时的影响
小程序代码的注入耗时直接影响小程序的启动耗时。耗时长短与当前页面结构复杂度和页面使用的自定义组件数量有关。
由于「首页渲染」需要使用视图层的页面结构和样式信息,如果小程序代码注入耗时过长,会影响渲染数据从逻辑层到达视图层的时间,影响「首页渲染」的耗时。
虽然开发者不能直接修改视图层生成的 JS 代码,但是可以通过移除未使用的自定义组件等方式降低这部分耗时。
4. 首页(初次)渲染
在逻辑层小程序代码注入完成后,小程序框架会根据用户访问的页面,进行页面组件树初始化,生成初始数据发送到视图层,并依次触发首页的 Page.onShow, Page.onReady 生命周期。
初始数据包括 Page 初始化参数中 data 属性值,和部分比较早发出的 setData 数据(哪些 setData 可以计入首页渲染与渲染层和逻辑层之间的初始化时序相关,目前没有可以保证一定能够计入的情况)。
在完成视图层代码注入,并收到逻辑层发送的初始数据后,结合从初始数据和视图层得到的页面结构和样式信息,小程序框架会进行小程序首页的渲染,展示小程序首屏,并触发首页的 Page.onReady 事件。
小程序框架层面,以 Page.onReady 事件触发标志小程序启动过程完成。
对启动耗时的影响
首页渲染耗时是启动过程的最后一环,直接影响小程序的启动耗时。耗时长短与页面结构复杂度、参与渲染的自定义组件数量有关。建议开发者参考《首屏渲染优化》章节进行优化。
5. 首屏内容展示
小程序 Loading 消失,此时一般情况下用户应该能立刻看到首屏内容。
但是如果首页的主体内容依赖网络请求(例如 dlt.request)等异步来源,用户并不一定能立刻看到有意义的完整界面,可能看到的仍然是白屏界面。需要等待网络请求异步返回后,调用 setData 进行页面更新,才能呈现真正的页面。
通常情况下,开发者也会选择先展示「骨架屏」来避免白屏,以优化用户体验。
对启动耗时的影响
异步 setData 触发绘制的首屏内容展示不一定会计入启动耗时统计,但是会延迟用户看到页面内容的时间,影响用户体验。建议开发者参考《首屏渲染优化》章节进行优化。