2023-09-06
小程序
00
请注意,本文编写于 324 天前,最后修改于 324 天前,其中某些信息可能已经过时。

目录

小程序运行机制
启动时
更新机制
启动中的一些关键节点
双线程模型
启动阶段性能优化
代码拉取阶段
代码注入阶段
首屏渲染优化
运行时优化
合理使用setData
渲染性能优化
页面切换优化
内存优化
特殊场景的优化

本文是参考微信小程序官方文档提炼的内容, 个人学习笔记。

  1. 小程序技术与web技术很大程度的相似,很多在web上能进行的优化在小程序上同样可以;
  2. 研究小程序的性能前,先要深入了解小程序的运行机制;
  3. 性能和体验优化可围绕 “加载时机(懒/预)”、“启动or运行”、"空间换时间(缓存)", “场景”等维度去考虑

小程序运行机制

启动时

image.png

更新机制

image.png

启动中的一些关键节点

  • 1. 环境准备阶段,获取小程序基本信息   无法优化(微信内部机制)
  • 2. 紧跟小程序基础库更新  无法优化
  • 3. 代码拉取&注入阶段  可以优化
  • 4. 合适的生命周期函数节点(数据拉取/业务逻辑/渲染)
  • 5. Page.onReady事件派发、首屏渲染完成阶段

双线程模型

  • 视图层有多个,一个页面对应一个视图层
  • 逻辑层只有一个,方便状态复用
  • 视图层和逻辑层都是沙盒环境
  • 视图层本质是Webview,使用了Exparser框架自定义组件,与WebComponentShadowDom高度相似,区别是css不隔离,并内置了一些组件及原生组件,Exparser可以在webview运行本质是执行了一些script垫片, 所以小程序有代码注入阶段一说法。
  • 逻辑层也是一个沙盒环境,隔离了一些window对象,新增了一些小程序对象(wx, Page, Component
  • 逻辑层和视图层通过JS bridge通信,数据序列化传输,这里是一个瓶颈,所以有setData优化及wxs技术

启动阶段性能优化

代码拉取阶段

该阶段既能减少代码下载时间又能减少代码注入的时间

  • 分包
    • 单个包2M,最多20M, 根据具体也如场景进行分包, 如将tabbar页面放在主包中
  • 独立分包
    • 如果对启动性能有很高的要求,可以将一些 广告、活动页或支付页等相对独立的页面放在独立分包中
  • 分包预加载
    • 优点:提高后续操作的体验,缺点:耗费一些流量
  • 分包异步化
    • 如果 分包B与分包C同时依赖一个通用组件 commonA,默认会将commonA组件打到主包中,更好的方案时将分包共同依赖的组件打包到另一个包中
  • treeSharking ? 开发者工具会进行treeSharking吗? 还是通过通过构建工具进行treeSharking? TODO
  • 小程序已经内置了corejs垫片,所以不需要处理es6 APIbabel只需处理es6句法(新语法)
  • 控制代码包内的资源文件
    • 图片视频音频字体等,可以考虑使用cdn

代码注入阶段

通常情况下,在小程序启动时,启动页面依赖的所有代码包(主包、分包、插件包、扩展库等)的所有 JS 代码会全部合并注入,包括其他未访问的页面以及未用到自定义组件,同时所有页面和自定义组件的 JS 代码会被立刻执行。这造成很多没有使用的代码在小程序运行环境中注入执行,影响注入耗时和内存占用。

  • 按需注入 "lazyCodeLoading": "requiredComponents" app.json 里面配置
  • 用时注入,在按需注入的基础上配置占位元素
  • 启动时减少同步API调用
  • 启动时避免复杂的运算
  • 周期性更新

首屏渲染优化

First Paint/First Contentful Paint

  • 使用「按需注入」和「用时注入」
  • 初始化渲染缓存 一般用于静态内容的页面
  • 骨架瓶 一般用于动态内容,与前者不建议一起使用,只是缓解用户等待的焦虑,事实上还略有增加首屏渲染时间
  • 精简首屏数据/提前请求/缓存数据
  • 合理规划版本发布(一定程度降低冷启动的时间)
  • 数据预拉取

运行时优化

合理使用setData

  • 减少setData频次
  • 减少setData数据量,只传渲染更新的最小量数据
  • 需要频繁更新的页面元素(例如:秒杀倒计时),可以封装为独立的组件,必要时可以使用 CSS contain 属性限制计算布局、样式和绘制等的范围。
  • 控制后台的setData

渲染性能优化

  • 适当监听页面或组件的scroll事件
  • 选择高性能的动画实现方式
    • 优先使用 CSS 渐变、CSS 动画、或小程序框架提供的其他动画实现方式完成动画;
    • 如果上述方式不能满足,可以使用 WXS 响应事件 ,减少callMethod方法调用
    • requestAnimationFrame代替定时器,节流
    • 高频渲染的地方抽取成组件
  • 使用 IntersectionObserver 监听元素曝光
  • 控制 wxml 节点数量及层级
  • 图片优化
    • 使用图片服务器压缩剪裁图片
    • 图片懒加载
    • 图片定高定宽,避免滥用widthFix/heightFix 模式

页面切换优化

非常建议了解下页面切换的执行流程 image.png

从上图可以看出主包及公共代码一定要精简,是对页面切换影响最大的因素。

  • 首屏渲染优化
  • 提前请求数据,页面之间可以通过 EventChannel 进行通信
  • 控制预加载下个页面的时机

内存优化

  • 合理使用分包加载, 使用按需注入和用时注入
  • web内存泄漏垃圾回收的方法同样适用
    • 未清理的定时器
    • 闭包及时回收
    • 事件监听未及时解绑 wx.offLocationChange

特殊场景的优化

  • 长列表
  • 滚动监听

 完结 

以下内容为草稿

微信小程序性能指标

image.png

  1. 微信:微信公众平台-小程序---文档
  2. 支付宝:蚂蚁金服开发平台-小程序---文档
  3. 淘宝:淘宝开发者平台---文档
  4. 百度:智能小程序 --- 文档

本文作者:郭敬文

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!