小程序启动流程介绍
在进行启动优化之前,需要先了解小程序的启动过程。理解各个阶段的作用和耗时因素,可以帮助开发者更有针对性地选择优化手段。
小程序启动的各流程不是完全串行的,部分流程会并行执行。总启动耗时不等于各阶段耗时的简单加和。
启动流程概览
小程序启动过程主要包含以下阶段:
sequenceDiagram
autonumber
participant User as 用户
participant Runtime as 客户端
participant Service as 逻辑层代码注入
participant View as 视图层
participant Net as 网络
%% 启动
User->>Runtime: 打开小程序
par 资源准备
Runtime->>Runtime: 运行环境初始化
and
Runtime->>Net: 获取小程序信息
and
Runtime->>Net: 下载代码包
end
%% 代码注入
Runtime->>Service: 注入逻辑层代码
Runtime->>View: 注入视图层代码
%% 生命周期与首屏关键路径
Service->>Service: 执行 App/Page 生命周期
%% 首屏关键路径
Service->>View: setData(初始数据)
View-->>User: 首屏绘制完成
%% 首屏后更新
Service->>Net: 异步数据请求
Net-->>Service: 返回数据
Service->>View: setData(页面更新)1. 资源准备
1.1 运行环境准备
小程序的运行环境包括:
- 小程序进程
- 客户端原生系统组件和 UI 元素(导航栏、tabBar 等)
- 渲染页面使用的 WebView 容器
- JavaScript 运行引擎
- 小程序基础库
部分环境(如 JavaScript 引擎、基础库)需要在执行小程序代码之前准备完成,其他部分会在启动过程中并行初始化。
为了降低运行环境准备对启动耗时的影响,客户端会根据用户的使用场景和设备资源状况,在小程序启动前对运行环境进行预加载。
1.2 小程序信息获取
客户端需要从后台获取小程序的基本信息(版本、配置、权限等)。这些信息会在本地缓存,并通过一定机制更新。
对启动耗时的影响
- 首次访问或版本更新时,信息获取会增加启动耗时
- 耗时主要受网络环境影响
- 频繁发布版本会导致用户启动时同步请求比例上升,建议合理规划版本发布节奏
1.3 代码包下载
小程序启动时需要下载代码包。和信息获取类似,代码包也有缓存机制:
对启动耗时的影响
- 下载耗时是启动过程的重要瓶颈
- 耗时与网络环境和代码包压缩后大小直接相关
- 开发者应尽量控制代码包体积,参考 代码包体积优化
2. 代码注入
2.1 逻辑层代码注入
小程序启动时需要读取代码包中的配置和代码,注入到 JavaScript 引擎中执行。在此过程中会触发:
App.onLaunch生命周期App.onShow生命周期
对启动耗时的影响
- 代码量和复杂度:代码越多、逻辑越复杂,注入时间越长
- 同步接口调用:启动时调用同步 API 会阻塞注入过程
- 复杂计算:启动时执行大量计算会延长注入时间
2.2 视图层代码注入
开发者编写的样式和模板代码会编译为 JavaScript 注入到视图层,包含页面渲染所需的结构和样式信息。逻辑层和视图层的代码注入是并行进行的。
对启动耗时的影响
注入耗时与页面结构复杂度和使用的自定义组件数量有关。
3. 首页渲染
逻辑层代码注入完成后,小程序框架会:
- 根据用户访问的页面进行页面组件树初始化
- 触发
Page.onLoad,开发者可在此设置初始数据 - 生成初始渲染数据发送到视图层,触发
Page.onShow - 视图层收到数据后进行首屏绘制
- 首屏绘制完成后触发
Page.onReady
Page.onReady 触发标志着小程序启动流程完成。
对启动耗时的影响
- 首页渲染耗时是启动过程的最后一环
- 耗时与页面结构复杂度和参与渲染的组件数量相关
- 参考 首屏渲染优化
4. 首屏内容展示
首页渲染完成后,小程序 Loading 消失。但如果首屏主体内容依赖异步网络请求,用户可能看到的仍是空白或骨架屏,需要等请求返回后通过 setData 更新页面才能呈现完整内容。
对启动耗时的影响
异步数据请求不计入启动耗时统计,但会延迟用户看到完整内容的时间,影响实际体验。
生命周期时序总结
常见问题
为什么首次打开比后续打开慢很多?
首次打开需要同步下载代码包和获取小程序信息,后续打开会使用本地缓存,省去了下载步骤。
为什么不同设备启动耗时差异很大?
- 设备性能不同(CPU、内存)
- 不同操作系统的进程管理机制不同
- 低端设备预加载的运行环境更容易被系统回收