微信小程序启动流程介绍

在进行启动优化之前,我们先介绍一下微信小程序的启动过程。了解微信小程序的启动流程,可以帮助开发者更有针对性地选择性能优化的手段,分析性能优化的效果。

本文的启动流程以安卓和 iOS 为准,其他平台可能会略有差异。

注:微信小程序启动的各流程不是串行的,会尽可能的并行。计算总启动耗时不能简单的分阶段加和。

下列图片简要描述了部分情况下的微信小程序启动流程(注意:其中矩形块的宽度不与对应阶段耗时成比例)。

微信小程序启动流程示意图

开发者可以通过wx.getPerformance接口中 entryType 为 navigation,name 为 appLaunch 的指标(PerformanceEntry),获取页面切换耗时时。

微信小程序启动过程主要包括以下几个环节:

1. 资源准备

1.1 运行环境准备

微信小程序的运行环境包括微信小程序进程、客户端原生部分的系统组件和 UI 元素(如 导航栏、tabBar 等)、渲染页面使用的 WebView 容器、开发者 JavaScript 代码的运行环境、微信小程序基础库等等。

部分环境(如 JavaScript 引擎、微信小程序基础库)需要在执行微信小程序代码之前准备完成,其他的会在启动过程中并行进行。运行环境的准备时间相对较长(尤其是在低端设备上),会对微信小程序启动产生严重影响。

环境预加载

为了尽可能的降低运行环境准备对启动耗时的影响,微信客户端会根据用户的使用场景和设备资源的使用情况,依照一定策略在微信小程序启动前对运行环境进行部分地预加载,以降低启动耗时。

我们希望微信小程序启动时尽可能都使用到预加载的环境,但由于受到访问场景、设备资源状况和操作系统调度的影响,并不能保证每次微信小程序启动时都可以命中预加载的环境

对启动耗时的影响

运行环境准备耗时较长,如果启动时没有命中预加载的环境,对微信小程序的启动耗时会有明显影响。耗时长短与平台、设备性能、预加载比例有关。

  • 由于系统功能和启动流程实现的差异,通常安卓系统运行环境准备耗时要远高于 iOS。
  • 低端机系统资源比较紧张,预加载的环境会更容易被系统清理,导致预加载比例偏低。
  • 预加载比例越高,平均启动耗时一般可以越低。

这部分逻辑完全由微信客户端控制,开发者目前无法直接进行优化。

1.2 微信小程序相关信息准备

在用户访问微信小程序时,微信客户端需要从微信后台获取微信小程序的头像、昵称、版本、配置、权限等基本信息,以对微信小程序进行必要的版本管理、权限控制和校验等。

为了在保证信息实时性的前提下,尽量降低对启动耗时的影响,这些信息会在本地缓存,并通过一定的机制进行更新。

信息的获取和更新需要发起网络请求。请求分为两种情况:

(1) 同步请求:会阻塞微信小程序的启动流程,影响微信小程序的启动耗时。有以下情况需要进行同步请求:

  • 首次访问:用户首次访问该微信小程序(或微信小程序被清理)时,客户端没有缓存,需要同步请求微信小程序相关信息。
  • 同步更新:微信会在后台定期检查经常使用的微信小程序是否更新。如果启动时已知微信小程序有新版本,会同步更新信息。
  • 强制更新:用户长时间未使用微信小程序时,为保障信息的实时性,会强制同步更新信息。

(2) 异步请求:与启动流程并行,不影响启动耗时。主要发生在:

  • 异步更新:已使用过的微信小程序,定期检查暂未发现微信小程序有新版本,则优先使用本地缓存的信息完成启动,并异步进行更新。

对启动耗时的影响

在用户首次访问微信小程序、微信小程序版本更新或使用长期未使用的微信小程序时,信息的获取和更新会影响微信小程序的启动耗时,耗时长短主要与网络环境有关。

从大盘来看,微信小程序版本发布时,会导致启动时需要同步请求的比例上升,进而导致平均启动耗时的上涨。因此,建议开发者合理规划版本发布。

这部分逻辑完全由微信客户端控制,开发者目前无法直接进行优化。

1.3 代码包准备

微信小程序启动时,需要根据用户访问的页面,从微信后台获取代码包地址,从 CDN 下载微信小程序代码包,并对代码包进行校验。根据微信小程序页面所在分包和使用的插件不同,一次启动可能需要下载多个代码包或插件包。

除了启动过程,代码包下载在页面跳转、预下载、使用分包异步化等过程中也会触发。

为了在保证用户尽可能访问新版本的前提下,尽量降低对启动耗时的影响,微信小程序代码包会在本地缓存,并通过更新机制进行更新。

和相关信息准备类似,代码包下载也会有同步和异步两种情况:

(1) 同步下载:会阻塞微信小程序的启动流程,影响微信小程序的启动耗时。有以下情况需要进行同步下载:

  • 首次下载:用户首次访问该微信小程序(或微信小程序被清理)时,客户端没有缓存,需要同步下载代码包。
  • 同步更新:对于微信小程序信息发生「同步更新」或「强制更新」的情况,如果检测到微信小程序版本更新,会同步下载代码包。

(2) 异步下载:与启动流程并行,不影响启动耗时。主要发生在:

  • 异步更新:对于微信小程序信息发生「异步更新」的情况,如果检测到微信小程序版本更新,会异步更新代码包。

为了降低代码包下载的耗时,我们采用了包括但不限于以下方式:

  • 代码包压缩:采用 Zstandard 算法对微信小程序代码包进行压缩,以尽可能降低下载过程中传输的数据量。
  • 增量更新:当代码包发生更新,不需要重新下载完整的代码包,只需要下载根据算法生成的体积很小的增量包进行更新。
  • 更高效的网络协议:下载代码包优先使用 QUIC 和 HTTP/2。
  • 预先建立连接:在下载发生前,提前和 CDN 建立连接,降低下载过程中 DNS 请求和连接建立的耗时。
  • 代码包复用:对每个代码包都会计算 MD5 签名。即使发生了版本更新,如果代码包的 MD5 没有发生变化,则不需要重新进行下载。

对启动耗时的影响

下载耗时是启动耗时中的重要瓶颈,在用户首次访问微信小程序或微信小程序版本更新时,代码包的下载会对启动耗时造成影响。耗时长短与网络环境,代码包压缩后大小,以及是否命中增量更新有关。

考虑到包大小对用户体验的影响,平台限制单个微信小程序代码包的大小上限为 2M。代码包上限的增加,对于开发者来说能够实现更丰富的功能,但对于用户来说也增加了流量和本地空间的占用。为了保证启动速度,开发者应该尽可能的控制启动时用到的代码包大小。具体方法可以参考《代码包体积优化》。

2. 微信小程序代码注入(逻辑层)

微信小程序启动时需要从代码包内读取微信小程序的配置和代码,并注入到 JavaScript 引擎中。在主包代码注入过程中,会触发微信小程序的 App.onLaunchApp.onShow 生命周期。如果微信小程序使用了插件或扩展库,在注入开发者代码之前,还会先注入对应插件和扩展库的代码。

为了降低微信小程序代码注入的耗时,我们采用了包括但不限于以下方式:

  • Code Caching:在部分平台上,微信客户端会使用 V8 引擎的 Code Caching 技术对代码编译结果进行缓存,降低非首次注入时的编译耗时。

注意:如果代码中使用了 use asm,会导致 V8 的 Code Caching 失效。

对启动耗时的影响

微信小程序代码的注入耗时直接影响微信小程序的启动耗时。耗时长短与代码复杂度、同步接口调用和一些复杂的计算有关。如果未启用「按需注入」,耗时还会与启动使用到分包内的页面和自定义组件总数有关

由于「首页渲染」需要使用逻辑层发送的数据,如果微信小程序代码注入耗时过长,会延迟「首页渲染」开始的时间。建议开发者参考《代码注入优化》章节进行优化。

3. 微信小程序代码注入(视图层)

开发者的 WXSS 和 WXML 会编译成 JavaScript 代码注入到视图层,包含页面渲染需要的页面结构和样式信息。

我们采用和「微信小程序代码注入(逻辑层)」相似的方式优化注入耗时。

视图层和逻辑层的微信小程序代码注入是并行进行的

对启动耗时的影响

微信小程序代码的注入耗时直接影响微信小程序的启动耗时。耗时长短与当前页面结构复杂度和页面使用的自定义组件数量有关。如果未启用「按需注入」,耗时还会与启动使用到分包内的页面和自定义组件总数有关

由于「首页渲染」需要使用视图层的页面结构和样式信息,如果微信小程序代码注入耗时过长,会影响渲染数据从逻辑层到达视图层的时间,影响「首页渲染」的耗时。

虽然开发者不能直接修改视图层生成的 JS 代码,但是可以通过使用「按需注入」、移除未使用的自定义组件等方式降低这部分耗时。

4. 首页(初次)渲染

在逻辑层微信小程序代码注入完成后,微信小程序框架会根据用户访问的页面,进行页面组件树初始化,生成首屏渲染相关数据发送到视图层,并依次触发首页的 Page.onLoad, Page.onShow 生命周期。

首屏渲染相关数据包括 Page 初始化参数中 data 属性值,和部分比较早发出的 setData 数据(哪些 setData 可以计入首页渲染与渲染层和逻辑层之间的初始化时序相关,目前没有可以保证一定能够计入的情况)。

在完成视图层代码注入,并收到逻辑层发送的首屏渲染相关数据后,结合从初始数据和视图层得到的页面结构和样式信息,微信小程序框架会进行微信小程序首页的渲染,展示微信小程序首屏,并触发首页的 Page.onReady 事件。

如果开启了「初始渲染缓存」,「首页渲染」可以直接使用缓存完成,不依赖逻辑层的初始数据,降低启动耗时。

微信小程序框架层面,以 Page.onReady 事件触发标志微信小程序启动过程完成

对启动耗时的影响

首页渲染耗时是启动过程的最后一环,直接影响微信小程序的启动耗时。耗时长短与页面结构复杂度、参与渲染的自定义组件数量有关。建议开发者参考《首屏渲染优化》章节进行优化。

如果启用了「按需注入」,部分组件代码注入会被延迟到本阶段执行,导致阶段耗时上涨,但总耗时一般会下降。

5. 首屏内容展示

「首页渲染」完成后,微信小程序启动流程完成,Loading 消失,此时一般情况下用户应该能立刻看到首屏内容。

但是如果首页的主体内容依赖网络请求(例如 wx.request)等异步来源,用户并不一定能立刻看到有意义的完整界面,可能看到的仍然是白屏界面。需要等待网络请求异步返回后,调用 setData 进行页面更新,才能呈现真正的页面。

通常情况下,开发者也会选择先展示「骨架屏」来避免白屏,以优化用户体验。

对启动耗时的影响

异步 setData 触发绘制的首屏内容展示不一定会计入启动耗时统计,但是会延迟用户看到页面内容的时间,影响用户体验。建议开发者参考《首屏渲染优化》章节进行优化。

常见问题

(1) 为什么「开发版」和「体验版」微信小程序启动比「正式版」慢一些?

「开发版」和「体验版」微信小程序的启动流程和代码包下载链路会和「正式版」有所差别,也会有更严格的权限控制,因此启动耗时要慢于「正式版」微信小程序。

对于「开发版」微信小程序,为了方便开发调试,基础库会启用很多调试相关的能力,例如 vConsole、sourceMap 等,日志输出的等级也会更低,因此启动耗时和页面切换耗时也会有一定延长。

(2) 为什么安卓和 iOS 的启动耗时差异那么大?

两个平台的设备性能、系统功能和启动流程实现存在一定差异:

  • iOS 设备的平均性能要好于安卓;
  • iOS 微信小程序和微信共用进程,而 Android 上微信小程序运行在独立进程,需要额外的进程创建和一些基础模块的初始化流程;
  • iOS 上需要使用系统提供的 WebView 和 JavaScript Core,初始化开销几乎可以忽略;
  • 安卓 UI 和系统组件的创建的开销远高于 iOS。

性能与体验

为什么要进行性能优化

微信小程序的性能和用户的体验之间的关系密不可分。在使用微信小程序的过程中,用户有时会遇到微信小程序打开慢、滑动卡顿、响应慢等问题,这些问题都与微信小程序的性能有关。性能问题归根到底就是用户体验的问题,如果不能得到很好的解决,会影响用户的正常使用,甚至退出微信小程序。

随着微信小程序的迭代,页面越来越多,功能越来越复杂,微信小程序的性能问题也越来越突出。在开发微信小程序的过程中,开发者不仅应该关注功能的实现,还应该将足够的精力投入到微信小程序性能的优化上,保障良好的用户体验。

如何进行性能优化

广义上讲,微信小程序的性能又可以分为「启动性能」和「运行时性能」两个主题。「启动性能」让用户能够更快的打开并看到微信小程序的内容,「运行时性能」保障用户能够流畅的使用微信小程序的功能。除了本身的功能之外,良好性能带来的良好用户体验,也是微信小程序能够留住用户的关键。

微信小程序的框架结合了 Web 开发和客户端开发的技术,并进行了进一步的创新。因此,一些 Web 开发中性能优化的方法同样适用于微信小程序,比如缓存的使用、网络请求的优化、代码压缩等等。此外,由于微信小程序技术框架的特点,微信小程序开发中也有一些特殊的性能优化方法。

在进行性能优化时,开发者可以参考本章节中的优化指引,并借助微信小程序提供的一些调试工具和性能数据。

启动性能

微信小程序启动是微信小程序用户体验中极为重要的一环,启动耗时过长会造成微信小程序用户流失,影响用户体验。

本章节的「启动」特指微信小程序冷启动,不包括微信小程序后台切前台的热启动。关于冷/热启动的定义,请参考微信小程序运行机制

1. 微信小程序启动的定义

微信小程序的启动过程以「用户打开微信小程序」为起点,到微信小程序「首页渲染完成」为止

「用户打开微信小程序」可能是由用户点击访问触发,也可能通过扫码、微信小程序跳微信小程序或 APP 打开微信小程序等入口触发。从扫码、APP 等场景打开微信小程序时,可能会有前置的跳转和校验流程,不包含在微信小程序启动流程的讨论范围之内。

微信小程序「首页渲染完成」的标志是首个页面 Page.onReady 事件触发。由于启动流程的差异,微信小程序定义的「首页渲染完成」不等同于浏览器的 DOMContentLoadedload 事件。

要了解微信小程序启动的具体流程,请参考《微信小程序启动流程》章节的介绍。

2. 打开率/到达率

微信小程序「首页渲染完成」次数与「微信小程序启动」次数的比值也被称为(PV)打开率或(PV)到达率。与之对应的 流失率 = 1 - 打开率

打开率受到下列因素影响:

  • 启动性能:启动耗时越长,白屏时间越久,用户越可能因为失去耐心而退出微信小程序,打开率也会越低;
  • 用户等待意愿:用户等待意愿越强,等待时间也会更久,在启动耗时一致的情况下,打开率也会越高。用户等待意愿与使用微信小程序的场景有关,例如:
    • 扫码、搜索等用户目的性较强的场景,通常等待意愿也更强;
    • 广告类的场景下,用户等待意愿较低,要获得较高的打开率,启动性能优化会更加有必要。

Errno错误码

在使用部分微信小程序 API / 组件时,抛出的异常(fail 回调 / Promise reject)Error 对象中除了带有 errMsg,还会带有通用错误码 errno

代码示例

wx.openBluetoothAdapter({
  success (res) {
    console.log(res)
  }
  fail (err) {
    console.log(err.errno)
  }
})

背景介绍

errno 错误码的出现是为了解决以下问题:

  • 目前部分 API 在出现错误时,只返回错误信息 errMsg,没有错误码。另一部分 API 虽然有 errCode,但没有形成统一格式规范。
  • 目前有 errCode 的 API 中,不同的 API 失败时返回的 errCode 粒度不同。部分 API 的 errCode 粒度太大,信息不足。
  • 相同的错误在不同的 API 中 errCode 未对齐,不便于开发者记忆和处理。

因此,我们设计了一套拥有统一规范的错误码errno,以帮助开发者更好地开发调试及处理错误。

errno 错误码有如下优点:

  • 在错误码格式上,拥有统一的设计规范。
  • 不同的 API 中出现的相同错误,对应的错误码一致。
  • 错误码中包含 API 类别信息,帮助开发者快速定位问题。
  • 不同 API 中的错误码粒度较为统一。

Error 对象中同时有 errno 错误码和 errCode 错误码时,一般以 errno 错误码为准
后续 errno 错误码会逐步推广到所有 API 接口,并取代现有的 errCode 参数,为开发者提供错误信息。

错误码设计

errno 错误码一般为 7 位数,第 1 – 2 位标识 API 接口的一级类目,第 3 – 4 位标识 API 接口的二级类目,第 5 – 7 位表示具体的错误类型。
例如: errno 错误码为 1504003 时,15 表示 API 接口的一级类目为 设备,04 表示 API 接口的二级类目为 NFC,003 表示具体的错误类型。
目前已接入 errno 的 API 接口涉及的类目包括:

  • 一级类目:00 – 通用错误码
  • 一级类目:01 – 基础
    • 二级类目:00 – 通用基础错误
    • 二级类目:03 – 更新
    • 二级类目:09 – 加密
  • 一级类目:06 – 网络
    • 二级类目:00 – 通用网络错误
    • 二级类目:02 – 发起请求
    • 二级类目:03 – 下载
    • 二级类目:04 – 上传
    • 二级类目:06 – mDNS
  • 一级类目:07 – 支付
    • 二级类目:00 – 通用支付错误
    • 二级类目:01 – 支付默认二级类目
  • 一级类目:11 – 媒体
    • 二级类目:07 – 实时音视频
  • 一级类目:13 – 文件
    • 二级类目:00 – 通用文件错误
    • 二级类目:01 – 文件默认二级类目
    • 二级类目:02 – fd接口
  • 一级类目:14 – 开放接口
    • 二级类目:16 – 视频号
  • 一级类目:15 – 设备
    • 二级类目:00 – 通用设备错误
    • 二级类目:04 – NFC
    • 二级类目:05 – Wi-Fi
    • 二级类目:09 – 低功耗蓝牙
    • 二级类目:10 – 蓝牙
  • 一级类目:20 – AI
    • 二级类目:02 – 人脸识别
    • 二级类目:03 – vision kit
    • 二级类目:04 – 机器学习

实时日志

背景

为帮助微信小程序开发者快捷地排查微信小程序漏洞、定位问题,我们推出了实时日志功能。开发者可通过提供的接口打印日志,日志汇聚并实时上报到微信小程序后台。开发者可从We分析“性能质量->实时日志->微信小程序日志”进入微信小程序端日志查询页面,或从“性能质量->实时日志->插件日志”进入插件端日志查询页面,进而查看开发者打印的日志信息。

如何使用

微信小程序/小游戏端

从基础库2.7.1开始,微信小程序端即可使用实时日志,小游戏端则从基础库2.14.4开始支持。

1、调用相关接口。打日志的接口是wx.getRealtimeLogManager,为了兼容旧的版本,建议使用如下代码封装一下,例如封装在log.js文件里面:

var log = wx.getRealtimeLogManager ? wx.getRealtimeLogManager() : null

module.exports = {
  debug() {
    if (!log) return
    log.debug.apply(log, arguments)
  },
  info() {
    if (!log) return
    log.info.apply(log, arguments)
  },
  warn() {
    if (!log) return
    log.warn.apply(log, arguments)
  },
  error() {
    if (!log) return
    log.error.apply(log, arguments)
  },
  setFilterMsg(msg) { // 从基础库2.7.3开始支持
    if (!log || !log.setFilterMsg) return
    if (typeof msg !== 'string') return
    log.setFilterMsg(msg)
  },
  addFilterMsg(msg) { // 从基础库2.8.1开始支持
    if (!log || !log.addFilterMsg) return
    if (typeof msg !== 'string') return
    log.addFilterMsg(msg)
  }
}

2、在页面的具体位置打印日志:

var log = require('./log.js') // 引用上面的log.js文件
log.info('hello test hahaha') // 日志会和当前打开的页面关联,建议在页面的onHide、onShow等生命周期里面打
log.warn('warn')
log.error('error')
log.setFilterMsg('filterkeyword')
log.addFilterMsg('addfilterkeyword')

完整的例子可以参考代码片段:https://developers.weixin.qq.com/s/aFYw1BmC7eak

插件端

从基础库2.16.0开始支持,插件端也支持了实时日志。为了让日志更具有结构性,以便后续进行更为复杂的分析,因此插件端采用新设计的格式。

1、调用相关接口 wx.getRealtimeLogManager,获取实时日志管理器实例:

const logManager = wx.getRealtimeLogManager()

2、在需要打日志的逻辑中,获取日志实例:

// 标签名可以是任意字符串,一个标签名对应一组日志;同样的标签名允许被重复使用,具有相同标签名的日志在后台会被汇总到一个标签下
// 标签可为日志进行分类,因此建议开发者按逻辑来进行标签划分
const logger = logManager.tag('plugin-onUserTapSth')

3、在合适位置打印日志:

logger.info('key1', 'value1') // 每条日志为一个 key-value 对,key 必须是字符串,value 可以是字符串/数值/对象/数组等可序列化类型
logger.error('key2', {str: 'value2'})
logger.warn('key3', 'value3')
logger.setFilterMsg('filterkeyword') // 和微信小程序/小游戏端接口一致
logger.setFilterMsg('addfilterkeyword') // 和<a href="https://weixin-xiaochengxu-kaifa.yuannext.com">微信小程序</a>/小游戏端接口一致

如何查看日志

登录We分析,从“性能质量->实时日志”进入日志查询页面。开发者可通过设置时间、微信号/OpenID、页面链接、FilterMsg内容(基础库2.7.3及以上支持setFilterMsg)等筛选条件查询指定用户的日志信息。如果是插件上报的实时日志,可从“微信小程序插件->实时日志”进入日志查询页面进行查询。

./log2.png

注意事项

由于后台资源限制,“实时日志”使用规则如下:

  1. 为了定位问题方便,日志是按页面划分的,某一个页面,在一定时间内(最短为5秒,最长为页面从显示到隐藏的时间间隔)打的日志,会聚合成一条日志上报,并且在微信小程序管理后台上可以根据页面路径搜索出该条日志
  2. 每个微信小程序账号,We分析基础版每天限制5000条日志,We分析专业版为50000条,且支持购买配置升级或购买额外的上报扩充包。日志根据版本配置,会保留7天/14天/30天不等,建议遇到问题及时定位。
  3. 一条日志的上限是5KB,最多包含200次打印日志函数调用(info、warn、error调用都算),所以要谨慎打日志,避免在循环里面调用打日志接口,避免直接重写console.log的方式打日志。
  4. 意见反馈里面的日志,可根据OpenID搜索日志。
  5. setFilterMsg和addFilterMsg 可设置类似日志tag的过滤字段。如需添加多个关键字,建议使用addFilterMsg。例如addFilterMsg(‘scene1’), addFilterMsg(‘scene2’),addFilterMsg(‘scene3’),设置后在微信小程序管理后台可随机组合三个关键字进行检索,如:“scene1 scene2 scene3”、“scene1 scene2”、 “scene1 scene3” 或 “scene2”等(以空格分隔,故addFilterMsg不能带空格)。以上几种检索方法均可检索到该条日志,检索条件越多越精准。
  6. 目前为了方便做日志分析,插件端实时日志只支持 key-value 格式。
  7. 实时日志目前只支持在手机端测试。工具端的接口可以调用,但不会上报到后台。
  8. 开发版、体验版的实时日志,不计入相关quota,即无使用上限。

filtermsg

微信小程序 Source Map

目前只在 iOS 6.7.2 及以上版本支持

微信小程序/小游戏在打包时,会将所有 JavaScript 代码打包成一个文件,为了便于开发者在手机上调试时定位错误位置,微信小程序/小游戏提供了 Source Map 支持。

在开发者工具中开启 ES6 转 ES5、代码压缩时,会生成 Source Map 的 .map 文件。开发版微信小程序中,基础库会使用代码包中的 .map 文件,对 vConsole 中展示的错误信息堆栈进行重新映射(只对开发者代码文件进行)。

如果使用外部的编译脚本对源文件进行处理,只需将对应生成的 Source Map 文件放置在源文件的相同目录下

如:

pages/index.js
pages/index.js.map
app.js
app.js.map

开发者工具会读取、解析 Source Map 文件,并进行将其上传

后续可以在微信小程序后台的运营中心可以利用上传的 Source Map 文件进行错误分析

注意事项

  1. Source Map 文件不计入代码包大小计算,也不会被包含在体验版/正式版代码包中。
  2. inline sourcemap 不计入代码包大小计算。
  3. 开发版代码包中由于包含了 .map 文件,实际代码包大小会比体验版和正式版大。

vConsole

在真机上,如果想要查看 console API 输出的日志内容和额外的调试信息,需要在点击屏幕右上角的按钮打开的菜单里选择「打开调试」。此时微信小程序/小游戏会退出,重新打开后右下角会出现一个 vConsole 按钮。点击 vConsole 按钮可以打开日志面板。

微信小程序和小游戏的 vConsole 展示内容会有一定差别,下图左边是微信小程序 vConsole,右边是小游戏 vConsole

vConsole 使用说明

由于实现机制的限制,开发者调用 console API 打印的日志内容,是转换成 JSON 字符串后传输给 vConsole 的,导致 vConsole 中展示的内容会有一些限制:

  • 除了 NumberStringBooleannull 外,其他类型都会被作为 Object 处理展示,打印对象及原型链中的 Enumerable 属性。
  • InfinityNaN 会显示为 null
  • undefinedArrayBufferFunction 类型无法显示
  • 无法打印存在循环引用的对象
let a = {}
a.b = a
console.log(a) // 2.3.2 以下版本,会打印 `An object width circular reference can't be logged`

针对上述问题,微信小程序/小游戏在使用 vConsole 时做了一些处理

  • 2.3.2 及以上版本,支持打印循环引用对象。循环引用的对象属性会显示引用路径,@表示对象本身。
const circular = { x: {}, c: {} }
circular.x = [{ promise: Promise.resolve() }]
circular.a = circular
circular.c.x0 = circular.x[0]

console.log(circular)
// "{a: '<Circular: @>', c: {x0: '<Circular: @.x[0]>'}, x: [{promise: '<Promise>'}]}"
  • 2.3.1 及以上版本,支持展示所有类型的数据。基础库会对日志内容进行一次转换,经过转换的内容会使用<>包裹。如:

    • <Function: func>
    • <Undefined>
    • <Infinity>
    • <Map: size=0>
    • <ArrayBuffer: byteLength=10>
  • 2.2.3 ~ 2.3.0 版本中,可以展示 ArrayBufferFunction 类型,undefined 会被打印为字符串 'undefined'

注:尽量避免在非调试情景下打印结构过于复杂或内容过长的日志内容(如游戏引擎中的精灵或材质对象等),可能会带来额外耗时。为了防止异常发生,日志内容超过一定长度会被替换为<LOG_EXCEED_MAX_LENGTH>,此时需要开发者裁剪日志内容。

调试

开发者可以借助下列工具进行微信小程序的调试。

  • vConsole:在手机上查看console API 输出的日志内容和额外的调试信息。
  • Source Map:还原 JS 错误堆栈
  • 真机调试: 利用开发者工具,通过网络连接,对手机上运行的微信小程序进行调试,帮助开发者更好的定位和查找在手机上出现的问题。
  • 实时日志:快捷地排查微信小程序漏洞、定位问题

四、获取微信小程序结算收入数据及结算主体信息(publisher_settlement)

需要向相应接口调用地址增加以下GET请求参数:

参数 是否必须 说明
page 数据返回页数
page_size 每页返回数据条数
start_date 获取数据的开始时间 yyyy-mm-dd
end_date 获取数据的结束时间 yyyy-mm-dd

请注意: 只要与获取数据的起止时间有重合,结算区间对应的数据都将返回。例如,请求2月11日至3月26日的数据,将会返回2月上半月、2月下半月、3月上半月、3月下半月四个结算区间的数据。


返回参数说明(publisher_settlement)

参数 说明
err_msg 返回错误信息
ret 错误码
body 主体名称
revenue_all 累计收入
penalty_all 扣除金额
settled_revenue_all 已结算金额
settlement_list: date 数据更新时间
settlement_list: zone 日期区间
settlement_list: month 收入月份
settlement_list: order 1 = 上半月,2 = 下半月
settlement_list: sett_status 1 = 结算中;2、3 = 已结算;4 = 付款中;5 = 已付款
settlement_list: settled_revenue 区间内结算收入
settlement_list: sett_no 结算单编号
settlement_list: mail_send_cnt 申请补发结算单次数
settlement_list: slot_revenue: slot_id 产生收入的广告位
settlement_list: slot_revenue: slot_settled_revenue 该广告位结算金额
total_num 请求返回总条数


返回数据包示例(publisher_settlement)

{
    "base_resp":{
        "err_msg":"ok",
        "ret":0
    },
    "body":"深圳市腾讯计算机系统有限公司",
    "penalty_all":0,
    "revenue_all":5178368698,
    "settled_revenue_all":2613696765,
    "settlement_list":[
        {
            "date":"2020-03-25",
            "zone":"2020年3月1日至15日"
            "month":"202003",
            "order":1,
            "sett_status":1,
            "settled_revenue":718926045,
            "sett_no":"XXX",
            "mail_send_cnt":"0",
            "slot_revenue":[
                {
                    "slot_id":"SLOT_ID_WEAPP_BANNER",
                    "slot_settled_revenue":34139443
                },
                {
                    "slot_id":"SLOT_ID_WEAPP_REWARD_VIDEO",
                    "slot_settled_revenue":684786602
                }
            ]
        }
    ],
    "total_num":1
}


三、获取微信小程序广告位清单(get_adunit_list)

需要向相应接口调用地址增加以下GET请求参数:

参数 是否必须 说明
page 返回第几页数据
page_size 当页返回数据条数
ad_slot 广告位类型名称
ad_unit_id 广告位id

请注意: 当需要获取全部广告位的清单时,无需传递广告位类型名称及广告位id;当需要获取某类型广告位的清单时,仅需传递广告位类型名称;当需要获取某广告位id的数据时,仅需传递广告位id。


返回参数说明(get_adunit_list)

参数 说明
err_msg 返回错误信息
ret 错误码
ad_slot 广告位类型名称
ad_unit_id 广告位ID
ad_unit_name 广告位名称
ad_unit_size 广告位尺寸
ad_unit_status 广告位状态


返回数据包示例(get_adunit_list)

{
    "base_resp":{
        "err_msg":"ok",
        "ret":0
    },
    "ad_unit":[
        {
            "ad_slot":"SLOT_ID_WEAPP_REWARD_VIDEO",
            "ad_unit_id":"adunit-e9418ee19XXXXX",
            "ad_unit_name":"rewaXXXX",
            "ad_unit_size":[
                {
                    "height":166,
                    "width":582
                }
            ],
            "ad_unit_status":"AD_UNIT_STATUS_ON",
            "ad_unit_type":"AD_UNIT_TYPE_REWARED_VIDEO",
            "appid":"wx0afc78670fXXXX",
            "video_duration_max":30,
            "video_duration_min":6
        }
    ],
    "total_num":1
}