FPS 面板

基础库 2.22.1 开始支持,低版本不生效。

为了便于开发者调试渲染层的交互性能,微信小程序基础库提供了选项开启 FPS 面板,开发者可以实时查看渲染层帧率。

启用方式

在 app.json 中,如下配置,则可在微信小程序启用 FPS 面板,展示当前的实时帧率、及当前时间窗口内的帧率波动范围。

{
  "debugOptions": {
    "enableFPSPanel": true
  }
}

请注意不要把这个配置项带到正式版本。

使用说明

  • FPS 面板是通过 webview 的 requestAnimationFrame 回调,使用 canvas 绘制的,本身可能会有一些额外的性能开销,但一般情况下可以忽略;
  • FPS 面板可以拖动到屏幕的任意位置;
  • 未启用同层渲染时,FPS 面板可能会被原生组件遮挡。

微信小程序开发者工具「模拟器」和「调试器」

微信开发者工具的「模拟器」和「调试器」,可以帮助开发者利用工具模拟微信小程序的表现,也包括了性能分析的能力。

需要开发者工具 1.05.2201240 及以上版本支持

逻辑层 JavaScript Profile

开发者可以使用「模拟器」中的「Performance」或「JavaScript Profiler」面板,分析微信小程序逻辑层的 JS 执行情况。

如果要分析启动过程中微信小程序代码注入的情况,可以点击「Performance」左上角第二个 reload 按钮。

详细的使用说明可参考 Chrome 的「Performance」、「JavaScript Profiler」面板

逻辑层内存调试

与真机调试 2.0 类似,开发者可以使用「模拟器」中的「memory」面板,获取微信小程序逻辑层的 JS 堆内存快照,分析内存分布情况,排查内存泄漏问题。

详细的使用说明可参考 Chrome 的「Memory」面板

视图层调试

需要最新工具 nightly 版本支持

开发者可以在模拟器底部打开当前页面的「视图层」调试工具。在工具中,可以通过「Performance」、「memory」、「Layer」、「Rendering」等面板调试微信小程序视图层的性能。

详细的使用说明可参考 Chrome 的对应面板

低端机模拟

开发者可以在模拟器中开启「低端机模拟」,开发者工具会对 CPU 使用等进行一定限制,模拟低端机的使用体验。

真机调试 2.0

微信开发者工具的「真机调试 2.0」功能,可以帮助开发者利用工具调试真机上的微信小程序表现,也包括了性能分析的能力。开启真机调试 2.0 的步骤请参考《真机调试 2.0 文档》。

内存调试

仅支持安卓设备

开发者可以使用「memory」面板,获取微信小程序逻辑层的 JS 堆内存快照,分析内存分布情况,排查内存泄漏问题。

详细的使用说明可参考 Chrome 的「Memory」面板

JavaScript Profiler

仅支持安卓设备

开发者可以使用「JavaScript Profiler」面板,分析微信小程序逻辑层的 JS 执行情况。如果要分析启动过程中微信小程序代码注入的情况,可以在代码中使用 debugger 来断点。

// app.js
debugger

App({
  onLaunch() {}
})

详细的使用说明可参考 Chrome 的「JavaScript Profiler」面板

性能与体验调试工具

为了协助开发者调试与优化微信小程序的性能与体验,我们提供了一些工具:

  • 真机调试 2.0:通过开发者工具调试真机运行环境。
  • 开发者工具「模拟器」和「调试器」:在开发者工具「模拟器」中对微信小程序视图层分析和进行低端机模拟,在「调试器」环境中进行 JS 性能、内存占用分析。
  • 代码质量分析面板:静态分析开发者代码,给出优化建议。
  • FPS 面板:展示页面当前的实时帧率
  • 性能面板
  • 体验评分:自动化检测微信小程序性能与体验问题,并为开发者提供优化建议。

产品体验分析

查看详细介绍
产品体验分析是一款帮助微信小程序提升拉新、留存、付费转化率的数据分析工具。它能够可视化还原用户操作现场,精准定位产品交互体验缺陷或功能bug。

功能介绍

会话回放

对于用户每一次与应用交互的全部过程,都会真实记录并进行回放。你可以查看用户在此次会话中的具体操作行为。

热力图

直观展示大多数用户是如何使用你的产品。你可以查看用户在产品使用中鼠标点击、页面停留的位置。分析页面元素的曝光度,优化页面信息展示。

转化分析

探索不同页面与事件的流量流转,绘制用户体验地图,发现并优化用户流失问题,提升用户转化率与留存率。

开始体验

前往查看操作说明

评测标准

诊断工具从启动性能、跳页性能、最佳实践、操作体验和网络性能五个方面进行评测。

部分启动性能指标含义与跳页性能指标相同,性能报告中区分首页和其它页面,可以更方便地排查启动流程中的问题。

名词解释

  • 长任务: 执行耗时超过 50ms 的函数。
  • 按需注入:仅注入当前访问页面所需的自定义组件和页面代码。
  • 用时注入:开启「按需注入」特性的前提下,「用时注入」可以指定一部分自定义组件不在微信小程序启动时注入,而是在真正渲染的时候才进行注入。

指标清单

分类 指标 未通过标准
启动性能 App 生命周期中的长任务 生命周期函数耗时 > 50ms
避免非必要的全局插件 存在全局引入的插件
使用「按需注入」 未开启「按需注入」
首页重定向 首页启动后立即重定向到其它页面
内联 base64 图片 首页 WXSS 中内联 base64 图片 > 10kB
跳页性能 同步 API 阻塞 页面渲染前多次调用同步 API
页面打开请求 页面纯请求耗时 > 200ms
声明但未使用到的组件 页面访问过程中未使用到的组件
页面生命周期中的长任务 页面生命周期函数耗时 > 50ms
优先展示顶部搜索框 新开页面未优先展示顶部搜索框
进入详情页复用图片 点击图片进入详情页未复用图片导致白屏
最佳实践 缓存 storage 结果 首页重复获取相同键值的本地缓存
合理控制本地缓存大小 本地缓存占用超过 50%
缓存 systemInfo 结果 getSystemInfo 同步&异步接口调用超过3次
避免未处理的 JavaScript 异常 存在未处理的 JavaScript 异常
脚本执行耗时过长 页面方法耗时 > 50ms
避免空的 onPageScroll 函数 存在空的 onPageScroll 函数
缓存 getLocation 结果 30s 内重复调用 getLocation
避免在 scroll 事件处理耗时逻辑 存在 scroll 事件处理耗时 > 10ms 或总耗时 > 150ms
适当调整图片大小 存在图片太大而有效显示区域较小
传送现代格式的图片 使用 webp 替代 JPEGPNG 图片
对图片进行高效编码 对图片进行适当压缩
使用视频格式制作动画内容 大型 GIF 转换为视频更为高效
避免 wx.on 类型接口导致的内存泄漏 页面销毁时仍未移除 wx.on 类型监听器
避免 observe 类型接口导致的内存泄漏 页面销毁时仍未停止 observe 类型监听器
操作体验 轮播组件切换时复用节点 轮播组件切换时未复用节点导致闪白
合理设置可点击元素大小 存在可点击元素宽高 < 20px
交互事件响应迅速 存在交互事件处理耗时 > 50ms 或总耗时 > 150ms
自定义 tabbar 切换时无闪烁 自定义 tabbar 切换时存在闪烁
网络性能 使用 HTTP/2 有请求未使用 HTTP/2
避免网络请求失败 存在网络请求失败
避免网络状态码异常 存在网络状态码异常
减少网络排队数量 网络排队个数>50 或平均排队耗时 > 1500ms

性能诊断工具

简介

为了协助开发者更好地排查微信小程序的性能和体验问题,我们推出了<a href="https://weixin-xiaochengxu-kaifa.yuannext.com">微信小程序</a>性能诊断工具

诊断工具会从启动性能、跳页性能、最佳实践、操作体验和网络性能等方面对微信小程序进行检测,并给出针对性的优化建议,部分指标会尝试给出预估的优化空间。

使用方法

运行环境要求:

  • 基础库使用 3.7.0 及以上版本
  • iOS 客户端版本 >= 8.0.54
  • Android 客户端版本 >= 8.0.55
  • 开发者工具 Nightly >= 1.06.2411272

开发版/体验版 微信小程序可从微信小程序菜单开启诊断工具,正式版本不支持使用。

  1. 右上角菜单-开发调试-开启 Audits-重启并自动开启检测

会自动关闭当前微信小程序,下次打开时自动检测,页面中出现“检测中”标识。进入到需要检测的页面,操作微信小程序。

  1. 右上角菜单-开发调试-关闭 Audits

有任务结束弹窗弹出,点击导出数据有 json 文件分享到微信里。

  1. 将导出的 json 文件拖拽到开发者工具 Audits 面板进行可视化

注意事项

  1. 诊断工具仅在激活后会加载相关代码,并对 开发版/体验版 进行检测,正式版本即使激活也不会生效。
  2. 诊断工具是在运行时检测,覆盖范围依赖开发的操作路径,开发者应可能操作关键路径,触发页面滚动、轮播之类的操作。
  3. 诊断工具是体验评分的升级,少量指标会重叠,诊断工具致力于给出具体的可优化建议。

性能数据

为了帮助开发者更好地了解和分析微信小程序性能状况,我们在「微信小程序助手」微信小程序上提供了性能相关的数据统计。同时,开发者也可以根据业务需要自行上报和分析。

1. 获取性能数据

1.1 通过 We 分析

We 分析-「性能质量」-「性能数据」也提供部分性能数据的看板,目前还在不断完善中。

1.2 通过 wx.getPerformance 在微信小程序内获取

开发者可以使用 wx.getPerformance 获取当前微信小程序性能相关的信息,包括无法在 JS 代码中直接打点获取的一些时间信息。此外,开发者也可以在微信小程序中根据自身业务需要进行打点。

具体的指标说明如下:

  • appLaunch:微信小程序启动耗时。
    • 起点为用户点击微信小程序图标,或微信小程序被拉起的时间;
    • 终点为首个页面 LargestContentfulPaint 结束时间。
  • route:页面切换耗时。
    • 起点为触发页面切换;
    • 终点为页面 LargestContentfulPaint 结束时间;
    • 详情请参见页面切换性能文档。
  • firstRender:页面首次渲染耗时。
    • 起点为逻辑层收到路由事件,包括逻辑层页面与组件初始化、VD 同步、渲染层执行渲染的时间;
    • 终点为页面 onReady;
    • 详情请参见页面切换性能文档。
  • firstPaint(FP):页面首次绘制
    • 页面首次绘制(第一个像素渲染到屏幕上)的时间;
  • firstContentfulPaint(FCP):
    • 页面首次内容绘制(第一块内容渲染到屏幕上)的时间;
    • 具体含义可以参考 《First Contentful Paint》
  • largestContentfulPaint(LCP):
    • 页面最大内容绘制的时间;
    • 具体含义可以参考 《Largest Contentful Paint》
  • evaluateScript:逻辑层 JS 代码注入(含编译和执行)耗时。

内存优化

1. 合理使用分包加载

使用分包加载不仅能优化启动耗时,也能够实现页面、组件和逻辑较粗粒度的按需加载,从而降低内存的占用。详情请参考《启动优化-代码包体积优化》

2. 使用按需注入和用时注入

通过开启「按需注入」和「用时注入」,可以在运行时避免加载未使用到的页面和组件,降低运行时的内存占用。详情请参考《启动优化-代码注入优化》

3. 内存分析

如果要更精细地分析微信小程序逻辑层的内存分布情况,可以使用开发者工具调试器的「内存调试」或「真机调试 2.0」提供的「内存调试」能力。

4. 处理内存告警

当微信小程序占用系统资源过高,可能会被系统销毁或被微信客户端主动回收。在 iOS 上,当微信客户端在一定时间间隔内连续收到系统内存告警时,会根据一定的策略,主动销毁微信小程序,并提示用户「运行内存不足,请重新打开该微信小程序」。

建议微信小程序在必要时使用 wx.onMemoryWarning 监听内存告警事件,进行必要的内存清理。例如:释放一些暂时不用的组件或 JS 对象。

5. 微信小程序常见的内存泄露问题

存在内存泄露问题会导致微信小程序在运行过程中内存占用持续增长,引起微信小程序闪退或被微信强制销毁。

5.1 微信小程序长期持有页面实例,导致页面实例和引用的组件无法正常销毁

页面 unload 之后,基础库会从页面栈中将页面实例清理。正常情况下,JS 垃圾回收机制会将页面进行回收,释放内存。

但如果开发者代码中持有的页面实例(this)未释放,则会导致页面未被正常回收,引起内存泄露。建议开发者注意,并在 unload 中进行必要的清理。

案例一:页面实例被未解绑的事件监听引用

事件监听器中持有了页面的 this,如果页面销毁后监听未解绑,会导致页面无法释放。

Page({
  themeChangeHandler({ theme }) {
    this.setData({ theme })
  },
  onLoad() {
    this._handler = this.themeChangeHandler.bind(this)
    wx.onThemeChange(this._handler)
  },
  // 修复方法:unload 中解绑监听
  // onUnload() {
  //   wx.offThemeChange(this._handler)
  // },
})

案例二:页面实例被页面外变量或全局变量引用

函数闭包内持有了页面的 this,且函数被挂到全局或页面生命周期外的变量,会导致页面无法释放。

let languageListener = null

Page({
  onLoad() {
    getApp().userInfoChangeListener = ({ userName }) => {
      this.setData({ userName })
    }
    languageListener = ({ lang }) => {
      this.setData({ lang })
    }
  },
  // 修复方法:unload 中进行清理
  // onUnload() {
  //   getApp().userInfoChangeListener = null
  //   languageListener = null
  // },
})

案例三:页面实例被异步回调长时间引用

如果在长时间未返回的异步回调中访问了页面的 this,如持续时间过长的 setTimeoutsetInterval,耗时较长的 wx API 回调(如长时间的 wx.request 等),会导致页面无法释放。

Page({
  onLoad() {
    this._timer = setInterval(() => {
      this.setData({
        timerValue: Date.now()
      })
    }, 1000)
  },
  // 修复方法:unload 中进行清理
  // onUnload() {
  //   clearInterval(this._timer)
  // },
})

5.2 事件监听未及时解绑

事件监听结束后,应及时解绑监听器

const locationChangeListener = function (res) {
  console.log('location change', res)
}
wx.onLocationChange(locationChangeListener)
wx.startLocationUpdate()
// 监听结束后
wx.stopLocationUpdate()
// 修复方法:不使用后及时解绑监听
// wx.offLocationChange(locationChangeListener)

5.3 未清理的定时器

开发者在开发如「秒杀倒计时」等功能时,可能会使用 setInterval 设置定时器,页面或组件销毁前,需要调用 clearInterval 方法取消定时器。