• 微信小程序开发04 性能优化:借助微信开发者工具提升小程序性能


    你好,我是周俊鹏。

    前几节课我们分别从架构层(双线程模型)、链路层(授权模型)、和应用层(自定义组件)三个角度学习了小程序的技术要点。它们能帮你完成一个微信小程序的基本业务逻辑和交互逻辑。

    逻辑的第一诉求必然是支撑功能,对于端侧应用来说,功能是一方面,功能之外的用户体验也至关重要,良好的体验能加强用户对于应用的认同甚至依赖。小程序作为一种端侧应用,与其他应用端( Web/App )一样需要关注用户体验。用户体验有两个核心的要素:一是设计;二是性能。作为技术研发,我们关注的重点在于如何提升小程序的性能。

    在我看来,掌握底层的技术原理能帮我们写出性能更好的代码,不过理论在转化为实践时往往不是非常直观,所以在掌握理论的同时学会利用工具更为重要。

    今天我就结合微信开发者工具(简称微信 IDE)提供的小程序评分功能,来讲解一款高性能小程序背后的优化技巧。

    微信 IDE 的小程序评分功能位于调试器-> Audits 面板中:

    04-1.png

    点击“运行”之后,微信 IDE 会对当前的小程序项目进行评测(包括代码层面的检测、通过记录用户交互行为的体验检测)。最终从性能、体验和最佳实践三个维度分别打分以及综合分:

    • 性能评分是通过对页面渲染、网络、JS 脚本等方面的评估综合得来的;

    • 体验评分是从设计和交互等方面的评估而来,由于设计和交互存在一定的主观因素,所以体验的评分权当建议;

    • 最佳实践涉及的方面更宽泛,除了代码编写方面的建议(比如 01 讲我们提到尽量减少或聚合 setData 的调用),还有安全(比如尽量使用 HTTPS 增强安全性)和用户体验(比如适配不同宽度的屏幕)方面的建议。

    除了性能评分外,微信 IDE 给出的最佳实践方案中也有一部分与性能相关。接下来我就提取所有和性能相关的部分,剖分小程序性能优化的一些具体措施(用户体验跟这节课无关,我就不讲了)。

    小程序性能优化的具体维度

    微信 IDE 对小程序性能进行评分有以下几个维度(微信 IDE 的截图比较大,字体也比较小,所以我就不放截图了):

    1. 避免过大的 WXML 节点数目

    2. 避免执行脚本的耗时过长的情况

    3. 避免首屏时间太长的情况

    4. 避免渲染界面的耗时过长的情况

    5. 对网络请求做必要的缓存以避免多余的请求

    6. 所有请求的耗时不应太久

    7. 避免 setData 的调用过于频繁

    8. 避免 setData 的数据过大

    9. 避免短时间内发起太多的图片请求

    10. 避免短时间内发起太多的请求

    其实这 10 个性能的评分标准并不仅仅适用于微信小程序,有几条(2~6、9和10)是前端开发领域的通用性能指标,而且如果你用过 Vue/React 之类的MVVM 框架,以上指标可以全部应用到基于 Vue/React 框架开发的 Web 应用程序中。接下来我们一条条地剖析这几个指标对于性能优化的意义以及对应的解决方案。

    当然了,有些条目的优化方向是一致的(比如 7 和 8 是为了提高渲染性能),在剖析过程中我们会进行必要的聚合,这样更利于从全局的角度了解这些性能评分标准之间的关联。

    避免过大的 WXML 节点数目

    WXML 是基于 HTML 的一种 DSL(Domain Specific Language,领域专属语言),除了原生组件(比如 Camera 相机组件)以外,常规组件最终会被小程序的渲染线程(还记得 01 讲的渲染线程是什么吗?不记得的话要及时复习。)通过 WebView 渲染为 HTML ,所以从性能优化的角度上,HTML 的大部分性能优化方案均适用于 WXML,尽量减少节点数目就是方案之一。

    节点数目会影响渲染性能,要理解这句话,你要对浏览器的渲染流程有大概了解,来看下面这张图:

    Lark20201109-152322.png

    HTML 是 XML 的变体,在渲染的时候首先会被浏览器内核解析为 DOM 树,这是一种树形结构,然后会解析每个节点标签的类型、属性等要素,最后与 JavaScript 脚本和 CSS 结合起来进而在经过布局和绘制完成整个渲染流程。

    理论上 HTML 的节点数目和深度是没有限制的,但是从浏览器的渲染流程中不难看出,DOM 树的结构越复杂,渲染的管线就会越慢。我们再回想一下 01 讲的内容,当渲染线程执行的同时,逻辑线程是被阻塞的,也就是说如果渲染线程长时间占用了队列,这期间浏览器处于无法响应用户交互行为的“假死”状态,这对于用户体验是致命的。

    降低节点数目对于性能优化的另外一个原因,是与小程序 /Vue/React 这种 MVVM 框架的 DOM更新机制有关。这类框架在更新 UI 时不直接操作 DOM ,而是使用 VDOM( Virtual DOM,虚拟 DOM )技术来实现,VDOM 的高性能来源于高效的 Diff 算法,在内存中对 VDOM 树结构进行对比后提取差异点再映射到真实 DOM 中。

    而你不用关注 Diff 算法的细节,只需要知道它是基于树这种数据结构进行的,而树结构的复杂度会直接影响算法的执行耗时。所以如果你的小程序节点数目过多或者层次太深,那么在调用setData 更新 UI 时就会给 CPU 和内存过多的压力,进而可能造成小程序的假死。

    避免执行脚本的耗时过长

    执行脚本的耗时过长对于性能的不良影响主要体现在两个时期:

    • 第一是在小程序加载完成后的首次渲染期间;

    • 第二是小程序运行过程中的处理用户交互时期。

    JavaScript 脚本对小程序首次渲染的影响与浏览器环境下