微信小程序性能优化

前言

最近搞的小程序上线后,时间变得充足起来了,于是查阅文档搞下小程序的性能优化。

思路

一般性能优化分为首屏启动性能和运行时渲染性能两大项,而要针对性的优化,那么首先得要了解启动过程和运行时模型(小程序、H5、app内嵌webview等同理),下面总结下原生小程序上的性能优化。

优化启动性能

小程序启动流程

一般启动分为冷启动和热启动

  • 冷启动:如果用户首次打开,或小程序销毁后被用户再次打开,此时小程序需要重新加载启动,即冷启动。
  • 热启动:如果用户已经打开过某小程序,然后在一定时间内再次打开该小程序,此时小程序并未被销毁,只是从后台状态进入前台状态,这个过程就是热启动

一般优化启动性能是指优化冷启动,下面主要讲冷启动的优化。先来一张启动流程图:

从图中看出启动过程一般分为三个阶段:

  1. 环境准备
  • 小程序运行进程及运行环境的准备
  • 代码包下载、校验及初始化
  • 视图层系统组件、webview容器及原生组件的初始化
  • 逻辑层js引擎初始化及域创建
  1. 代码注入
  • 框架(wx api、小程序基础组件库)及第三方基础代码的初始化(weUI、插件)
  • 开发者代码注入
  1. 首屏渲染
  • 逻辑层页面初始化,这个时间点是 initDataSendTime,会有Page.onLoad事件派发
  • 视图层时间点走到viewLayerReaderStartTime,会有 Page.onShow事件派发
  • 开发者代码从后端拉取数据,准备data数据(非必须)
  • 页面渲染
  • 视图层时间点走到viewLayerReaderEndTime,会有 Page.onReady 事件派发标志着首屏渲染完成

优化点

这一过程主要考虑减少首屏加载包的大小,以及尽量缩短首屏渲染完成时间

减少包大小

  • 启用分包加载、代码里使用分包预加载减少下载分包等待时间
  • 静态资源常规压缩、上传cdn,代码里通过url访问(上传后需要把项目里的文件删除,或者配置project.config.json文件的 packOptions.ignore 字段,以指明上传时需要忽略的文件
  • 小程序项目里删除无用的静态资源文件、页面、组件等(官方的工具miniprogram-slim停止维护了...,不大管用,手动删除吧)

缩短首屏渲染完成(白屏)时间

App.onLuanch -> App.onShow -> Page.onReady事件标志首屏渲染完成。

  • 启用按需注入后,小程序仅注入当前访问页面所需的自定义组件和页面代码。未访问的页面、当前页面未声明的自定义组件不会被加载和初始化,对应代码文件将不被执行。
  • 在开启「按需注入」特性的前提下,「用时注入」可以指定一部分自定义组件不在小程序启动时注入,而是在真正渲染的时候才进行注入。
  • 在 App.onLuanch、App.onShow 事件里,避免耗时大的、同步的类 wx.xxxsync 接口调用(用异步的接口)
  • 配置数据预拉取和周期性更新机制,在page.onLoad里判断应用数据,加快页面内容显示
  • 使用数据缓存能力缓存接口数据
  • 对于低端机首次渲染需要较长时间的情况下,启用初始渲染缓存(二次打开生效)
  • 首页 生成骨架屏,在接口数据还没到来时,显示页面框架,减少用户焦虑

优化运行时渲染性能

先了解下小程序原理、重渲染机制

小程序原理

基于webview渲染的小程序架构使用逻辑层 AppService 和渲染层 WebView 的双线程模型,appservice线程负责js的执行,处理逻辑与数据,webview线程负责页面的渲染(wxml/wxss/wxs),native在两层之间提供数据传输和事件系统,如下:

重渲染机制

当每次调用setData更新数据时,都会和旧数据合并,并生成新节点树,然后使用新节点树有目标地将原节点树上需要更新的节点一一更新掉,这个过程就是重渲染(类比vdom diff),如下:

另外setData数据从逻辑层传到视图层所需时间与数据量的关系如下:

优化点

基于上面小程序原理知识及通用优化手段,有以下建议:

  • 减少wxml节点已层级(官方建议页面节点数少于1000,层数少于30,每个节点下的子节点数少于60)
  • 跟渲染无关的数据不要放到data里
  • 尽量合并setData的调用(promise.all)、尽量减少每次setData设时的数据量(如只更新大列表中的某一项的某个属性时可以用计算属性更新,如下:)
js 复制代码
// ...
const listData = this.data.listData;
this.setData({
  [listData[index].title]: '要更新啦',
  [listData[index].like]: true,
  // ...
})
// ...
  • 频繁触发的事件使用WXS脚本,在视图层完成事件处理
  • 使用 worker 与 WXWebAssembly 执行耗时任务
  • 对于长列表渲染、瀑布流布局等,可以切换成skyline渲染引擎,利用其提供的组件实现

工具

另外微信开发者工具上还有一些工具可以协助我们进行性能优化

  • performance(同web)
  • memory(同web)
  • audits 体验评分:定位和识别小程序运行过程中的体验问题,从性能、体验、最佳实践三个维度对小程序进行分析,同时提供优化建议
  • 代码质量 面板:通过静态代码检查发现问题并给出建议

评估优化

怎么评估优化效果(PPT数据展示~)呢,微信提供了几种查看性能数据的方法,建议使用 wx.getPerformance 接口直接获取当前小程序性能相关的信息,包括无法在 JS 代码中直接打点获取的一些时间信息,主要指标如下:

参考

相关推荐
里欧跑得慢1 小时前
CSS 模块化架构的演进:BEM、CSS Modules 到 CSS-in-JS 的反思
前端·css·flutter·web·css-in-js
IT_陈寒1 小时前
Vue的computed属性把我坑惨了,原来我一直用错姿势
前端·人工智能·后端
小灰灰搞电子2 小时前
Rust+Slint 实现温度计源码分享
前端·rust·slint
计算机魔术师2 小时前
面壁智能 OpenBMB 推出 MathForm,面向 Lean 4 数学自动形式化的开源框架、数据集与模型
前端
NeilCarmack2 小时前
Deepseek-harness增加桌面版端序列:第 2 讲 · spawn Electron:当前进程如何“交棒“
前端·javascript·electron
上海魁鲸科技有限公司3 小时前
APS高级排产系统到底有什么用?一文讲清功能、选型与落地建议
前端·microsoft·excel
陈随易3 小时前
Bun v1.4 更新总结:把浏览器、图片、定时任务和工程工具都装进一个运行时
前端·后端·程序员
东风破_5 小时前
TypeScript 高级类型进阶:keyof、Exclude、Record 与类型组合思想
前端·后端·typescript
DS随心转插件5 小时前
Grok生成的html怎么导出——AI导出鸭:大模型结构化输出的“最后一公里”工程化解构
前端·人工智能·ai·html·豆包·deepseek·ai导出鸭
এ慕ོ冬℘゜5 小时前
使用 jQuery 动态渲染表格与状态切换
前端·javascript·jquery