小程序开发总结
1、音频与视频需要审核才可以使用
2、api命名规则:
(1)、on开头的是监听某个事件是否触发
(2)、以Sync
结尾的 API 都是同步 API
(3)、大部分API都接收一个object作为参数,参数的回调函数有success
,fail
,complete
3、事件源属性:type target currentTarget timeStamp detail touch changedtouch
4、引用:WXML 提供两种文件引用方式import
和include
5、小程序判断开发版、体验版、审核版、开发工具版以及正式版本,网络请求的请求头referer,中的version如果是0,表示开发版、体验版、以及审核版,如果是devtools表示为开发工具,其它的是正式版本
6、wx.requset的并发请求是10个;
7、同一个微信用户,同一个小程序 storage 上限为 10MB。
8、onReachBottom不触发
page注册了这个方法,就是不触发。需要初始化页面高度大于1屏
9、本地图片开发工具显示真机不显示
用image不用backgorund
10、收集formID的时候首屏出现黑色边框,且点击首屏元素获取的是其它地方的元素
button{position: static;} view{height: 1000px;}
<form bindsubmit="submit" report-submit='true'>
<button form-type="submit" class="feed_title">
fdsfsd
</button>
</form>
<view></view>
解决方法:button的position不能用static,可能是微信框架的一些限制吧
11、canvas的api,在页面中,api的参数this不是必填的,在组件中就是必填的
12、小程序跳转小程序白名单的限制为10条,但是如果是小程序码图片预览的话,不受这个限制,可以直接识别小程序码跳转
13、wxs可以在wxml中写逻辑,<wxs module="tools">
14、setData使用规则:不频繁使用setData、setData不设置大量的数据、与界面渲染无关的数据最好不要设置在data中,可以考虑设置在page对象的其他字段下、切换到后台的页面不使用setData,和前台页面共同占用逻辑线程、利用setData进行列表局部刷新
15、小程序根目录下的 sitemap.json
文件用来配置小程序及其页面是否允许被微信索引
16、小程序冷启动会进入首页或上次退出的页面,页面退出的时候可以在onSaveExitState
保存退出数据,设置超时时间
一、浏览文档记录:
1、网页开发渲染线程和脚本线程是互斥的,这也是为什么长时间的脚本运行可能会导致页面失去响应,而在小程序中,二者是分开的,分别运行在不同的线程中。小程序的逻辑层和渲染层是分开的。
2、小程序的运行环境分成渲染层和逻辑层,其中 WXML 模板和 WXSS 样式工作在渲染层,JS 脚本工作在逻辑层。小程序的渲染层和逻辑层分别由2个线程管理:渲染层的界面使用了WebView 进行渲染;逻辑层采用JsCore线程运行JS脚本。一个小程序存在多个界面,所以渲染层存在多个WebView线程,这两个线程的通信会经由微信客户端(下文中也会采用Native来代指微信客户端)做中转,逻辑层发送网络请求也经由Native转发。
3、微信客户端在打开小程序之前,会把整个小程序的代码包下载到本地。
4、在渲染完界面之后,页面实例就会收到一个 onLoad
的回调,你可以在这个回调处理你的逻辑。
二、总结:
1、小程序为什么渲染这么快:
(1)、安装包缓存
(2)、独立渲染线程,渲染层和逻辑层可以同时进行,通过数据驱动,不直接操作DOM,使用Virtual DOM,进行局部更新
(3)、分包加载
(4)、webview预加载,提前新建WebView,准备新页面渲染
(5)、原生组件
2、小程序包的概念:
分包加载、分包预加载、独立分包(直接下载分包,不加载主包的内容)
3、首屏优化建议:
初始渲染缓存("initialRenderingCache": "static"
)、数据预拉取(冷启动的时候通过微信后台提前向第三方服务器拉取业务数据)
三、题外话
1、项目管理成员负责统筹整个项目的进展和风险、把控小程序对外发布的节奏;产品组提出需求;设计组与产品讨论并对需求进行抽象,设计出可视化流程与图形,输出设计方案;开发组依据设计方案,进行程序代码的编写;代码编写完成后,产品组与设计组体验小程序的整体流程;测试组编写测试用例并对小程序进行各种边界测试;
性能概论:
启动性能
小程序启动是小程序用户体验中极为重要的一环,启动耗时过长会造成小程序用户流失。
本章节的启动只包括小程序冷启动,不包括小程序后台切前台的热启动。
一、启动流程
在进行启动优化之前,先简单介绍以下小程序的启动过程。在小程序启动过程中,主要包括以下几个方面:
- 注 1:小程序启动的这些部分不是串行完成的,会尽可能的并行进行。
- 注 2:小程序启动各部分不是每次启动都完整进行的,会尽可能的利用缓存。
1. 资源准备
1.1 小程序相关信息准备
在用户访问小程序时,微信客户端需要从微信后台获取小程序的配置、版本、权限等相关信息,以对小程序进行必要的版本管理、权限控制和校验等。
对启动耗时的影响
信息的获取和更新会影响小程序的启动耗时,尤其体现在用户首次访问小程序时。
为了在尽量降低影响启动耗时的情况下保证信息的实时性,这些信息会在本地缓存,并通过一定的机制定期进行更新。
1.2 小程序运行环境准备
在执行小程序代码之前,微信客户端需要准备小程序运行的基础环境。
小程序的运行环境包括小程序进程、原生部分的 UI 元素(如 导航栏、tabBar等)、渲染页面使用的 WebView 容器、运行开发者 JS 代码的 JS 引擎、小程序基础库等等。
对启动耗时的影响
运行环境的准备耗时较长,对小程序的启动耗时有明显影响。
为了尽可能的降低运行环境准备对启动耗时的影响,微信客户端会根据用户的使用场景和设备资源的使用情况,提前对运行环境进行部分地预加载。但由于受到设备资源和操作系统调度的影响,目前很难保证每次小程序启动时都有预加载的环境。
1.3 小程序代码包准备
小程序启动时需要从服务器获取代码包地址、下载小程序代码包,并对代码包进行校验。根据小程序页面所在分包和使用的插件不同,一次启动可能需要下载多个代码包或插件包。
当小程序版本发生更新时,微信客户端还需要对代码包进行增量更新。
对启动耗时的影响
下载耗时是启动耗时中的重要瓶颈,与代码包或增量包的体积正相关。微信采用 ZSTD 算法对小程序代码包进行压缩,以尽可能降低下载过程中传输的数据量。
考虑到包大小对用户体验的影响,平台限制单个代码包的大小上限为 2M。代码包上限的增加对于开发者来说,能够实现更丰富的功能,但对于用户来说,也增加了下载流量和本地空间的占用。为了保证启动速度,开发者应该尽可能的控制代码包大小。
2. 开发者代码注入(逻辑层)
小程序启动时需要从代码包内读取小程序的配置和代码,并注入到 JS 引擎中。在主包代码注入过程中,会触发小程序的 App.onLaunch
和首次 App.onShow
生命周期。在开发者代码注入完成后,框架侧会根据用户访问的页面进行一些页面数据初始化工作,触发首页的 Page.onLoad
, Page.onShow
事件。
对启动耗时的影响
开发者代码的注入耗时直接影响小程序的启动耗时。在主流的 JS 引擎中,代码注入耗时包括编译和执行等环节,代码量、同步接口调用和一些复杂的计算,都会影响注入耗时。
由于首页渲染需要使用逻辑层发送的数据,如果开发者代码注入耗时过长,也会延迟首页渲染开始的时间。
在部分平台上,微信客户端会使用 V8 引擎的 Code Caching 技术对代码编译结果进行缓存,降低二次注入时的编译耗时。
3. 开发者代码注入(渲染层)
开发者的 wxss 和 wxml 会经过编译注入到渲染层,包含页面渲染需要的页面结构和样式信息。渲染层的注入耗时主要和页面结构复杂度和使用的自定义组件数量有关。
渲染层和逻辑层的开发者代码注入是并行进行的。
对启动耗时的影响
由于首页渲染需要使用渲染层的页面结构和样式信息,如果开发者代码注入耗时过长,会延迟首页渲染开始的时间。
4. 首页(初次)渲染
在开发者代码注入完成后,结合逻辑层得到的数据和渲染层得到的页面结构和样式信息,小程序框架会进行小程序首页的渲染,展示小程序首屏,并触发首页的 Page.onReady
事件。Page.onReady
事件触发标志小程序启动过程完成。
对启动耗时的影响
首页渲染耗时主要受页面结构和参与渲染的数据量影响。
二、关键概念
在讨论小程序启动耗时时,需要明确几个概念:
1. 小程序首屏渲染完成
从开发者角度看,小程序首屏渲染完成的标志是首页 Page.onReady
事件触发。
从框架的角度来说,小程序的首屏的内容是基于小程序的初始数据,以及在渲染开始前到达的 setData 数据渲染的。
首屏渲染完成不表示小程序页面一定有完整内容,开发者触发的 setData
(例如通过 wx.request
异步请求数据)不一定能参与到首屏渲染中。
由于框架和启动流程的差异,小程序定义的首屏渲染完成不等同于浏览器的 load 事件。
2. 小程序启动阶段
从用户点击访问小程序到小程序首屏渲染完成(首页 Page.onReady
事件触发)。
3. 打开率/到达率
小程序首屏渲染完成 PV 与 用户点击访问小程序 PV 的比值。流失率 = 1 - 打开率
三、启动性能优化
在启动流程中,小程序代码包准备、开发者代码注入和首页渲染是与开发者相关的,开发者可以进行一定的优化工作。其他部分目前开发者暂时无法干预,框架侧负责进行持续的优化。
1. 小程序代码包优化
代码包优化的核心手段是降低代码包大小,代码包大小直接影响了下载耗时,影响用户启动小程序时的体验。
开发者可以采取以下手段优化代码包大小:
1.1 分包加载
使用 分包加载 是优化小程序启动耗时效果最明显的手段。建议开发者按照功能划分,将小程序的功能按使用频率和场景拆分成分包,实现代码包的按需加载。
分包加载具有以下优势:
- 承载更多功能:小程序单个代码包的体积上限为 2M,使用分包可以提升小程序代码包总体积上限,承载更多的功能与服务。
- 降低代码包下载耗时:使用分包后可以显著启动时需要下载的代码包大小,在不影响功能正常使用的前提下明显提升启动耗时。
- 降低开发者代码注入耗时:小程序启动时会一次性注入全部的开发者代码,使用分包后可以降低注入的代码量,从而降低注入耗时。
- 降低页面渲染耗时
此外,结合分包加载的几个扩展功能,可以进一步优化启动耗时:
在使用「分包加载」后,虽然能够显著提升小程序的启动速度,但是当用户在使用小程序过程中跳转到分包内页面时,需要等待分包下载完成后才能进入页面,造成页面切换的延迟,影响小程序的使用体验。分包预下载便是为了解决首次进入分包页面时的延迟问题而设计的。
但小程序中的某些场景(如广告页、活动页、支付页等),通常功能不是很复杂且相对独立,对启动性能有很高的要求。独立分包可以独立于主包和其他分包运行。从独立分包中页面进入小程序时,不需要下载主包。建议开发者将部分对启动性能要求很高的页面放到特殊的独立分包中。
独立分包和分包预下载可以配合使用,获得更好的效果,详情请参考独立分包与分包预下载教程
1.2 代码重构和优化
通过代码重构,降低代码冗余。在使用如 Webpack 等打包工具时,要尽量利用 tree-shaking 等特性去除冗余代码,也要注意防止打包时引入不需要的库和依赖。
1.3 控制代码包内图片等资源
避免在代码包中包含或在 WXSS 中使用 base64 内联过多、过大的图片,应尽量采用网络图片。代码包内的图片一般应只包含一些体积较小的图标。声音、视频等其他类型的资源应尽量避免放到代码包中。
小程序代码包在下载时会使用 ZSTD 算法进行压缩,降低下载时传输的数据量。这些资源文件会占用大量代码包体积,并且通常难以进一步被压缩,对于下载耗时的影响比代码文件大得多。
1.4 及时清理没有使用到的代码和资源
在日常开发的时候,我们可能引入了一些新的库文件,而过了一段时间后,由于各种原因又不再使用这个库了,我们常常会只是去掉了代码里的引用,而忘记删掉这类库文件了。
目前小程序打包是会将工程下所有文件都打入代码包内,也就是说,这些没有被实际使用到的库文件和资源也会被打入到代码包里,从而影响到整体代码包的大小。
2. 开发者代码注入优化
开发者代码注入的优化可以从优化执行耗时和优化代码量两部分着手。
2.1 减少启动过程的同步调用
在小程序启动流程中,会注入开发者代码并顺序同步执行 App.onLaunch
, App.onShow
, Page.onLoad
, Page.onShow
。在小程序初始化代码(Page,App 定义之外的内容)和启动相关的几个生命周期中,应避免执行复杂的计算逻辑或过度使用Sync
结尾的同步API,如 wx.getStorageSync,wx.getSystemInfoSync 等。对于 getSystemInfo
, getSystemInfoSync
的结果应进行缓存,避免重复调用。
2.2 使用懒注入
通常情况下,在小程序启动时,启动页面所在分包和主包(独立分包除外)的所有JS代码会全部合并注入,包括其他未访问的页面以及未用到自定义组件,造成很多没有使用的代码注入到小程序运行环境中,影响注入耗时和内存占用。
自基础库版本 2.11.1 起,小程序支持仅注入当前页面需要的自定义组件和当前页面代码,以降低小程序的启动时间和运行时内存。开发者可以在 app.json
中配置:
{
"lazyCodeLoading": "requiredComponents"
}
注意:添加这项配置后,未使用到的代码文件将不被执行。
3. 页面渲染优化
3.1 提前首屏数据请求
大部分小程序在渲染首页时,需要依赖服务端的接口数据,小程序为开发者提供了提前发起数据请求的能力:
- 数据预拉取:能够在小程序冷启动的时候通过微信后台提前向第三方服务器拉取业务数据,当代码包加载完时可以更快地渲染页面,减少用户等待时间,从而提升小程序的打开速度。
- 周期性更新:在用户未打开小程序的情况下,也能从服务器提前拉取数据,当用户打开小程序时可以更快地渲染页面,减少用户等待时间。
3.2 骨架屏
在页面数据未准备好时(如需要通过网络获取),尽量避免展示空白页面,应先通过骨架屏展示页面的大致结构,请求数据返回后在进行页面更新。以提升用户的等待意愿。
3.3 缓存请求数据
小程序提供了wx.setStorage、wx.getStorage等读写本地缓存的能力,数据存储在本地,返回的会比网络请求快。如果开发者基于某些原因无法采用数据预拉取与周期性更新,我们推荐优先从缓存中获取数据来渲染视图,等待网络请求返回后进行更新。
3.4 精简首屏数据
我们推荐开发者延迟请求非关键渲染数据,与视图层渲染无关的数据尽量不要放在 data 中,加快页面渲染完成时间。
四、启动性能分析
1. 性能数据获取
1.1 小程序助手「性能分析」板块
小程序管理后台的性能数据还没有更新,正在规划改版中,建议在改版完成前开发者以小程序助手的性能数据为准。
建议开发者使用小程序助手中「性能分析」板块,持续关注小程序性能。性能分析从 启动性能、运行性能和网络性能 三个维度提供性能数据,供开发者根据平台、机型、网络环境和访问来源等条件做精细化分析。扫描下方小程序码即可立即体验。
目前,小程序助手中只包括微信客户端 >= 7.0.3 版本的正式版小程序数据。
1.2 通过 API 在小程序内获取
开发者可以在小程序中根据自身业务需有进行性能打点,也可以使用wx.getPerformance,获取当前小程序性能相关的信息。
在获取信息后,开发者可以自行上报或使用 wx.reportPerformance 进行测速。
1.3 体验评分
小程序工具中提供了体验评分工具,方便开发者能够及时发现小程序的体验问题。
2. 影响启动性能的因素
根据「启动流程」一节介绍的启动流程来看,影响小程序启动耗时的因素众多,分析小程序启动性能是一个比较复杂的过程。
对于同一个小程序,以下因素会直接影响平均启动耗时:
- 平台: 不同平台下(安卓、iOS、PC等)设备性能、操作系统、框架实现、优化方案存在较大差异,启动耗时也存在较大的差异。只有分平台比较启动耗时(包括各阶段的耗时)才有意义。
- 下载比例: 代码包下载和更新都会显著影响小程序启动耗时,在其他流程耗时稳定的情况下,下载比例升高会影响大盘启动耗时。
- 入口页面:不同页面启动时,根据所在分包的不同,需要下载的代码包数量和大小和代码注入量都存在差异。不同页面渲染耗时也存在差异。
- 机型分布:启动耗时和设备性能有较强关联,不同小程序或使用场景用户群体的差异可能导致机型分布的差异,进而影响大盘启动耗时。
- 网络环境:网络环境主要影响网络请求的耗时,如小程序信息获取、代码包下载等。
此外,下列情况也会间接影响启动耗时:
- 场景/访问来源:不同场景用户访问的页面不同,访问的目的性和自身的等待意愿也有差异,对启动耗时和打开率都有一定影响。
- 首次访问用户比例:用户首次访问小程序时,需要完整的进行小程序信息准备、代码包下载的流程、代码缓存也需要重新生成,启动耗时会比非首次访问高。
- 小程序版本更新:小程序版本更新时,用户需要更新小程序信息和代码包,代码缓存也需要重新生成,启动耗时会出现上涨。
关于「性能分析」板块数据
小程序助手中提供了启动过程中和开发者相关的下载耗时、js注入耗时和初次渲染耗时供开发者优化参考。
这里需要注意的是,启动总耗时 ≠ 下载耗时 + js 注入耗时 + 初次渲染耗时
。在启动过程中,下载不一定发生,也不一定只下载一个代码包。js 注入耗时和渲染耗时也会受缓存更新而发生波动。
各阶段耗时的下降不一定反应在总耗时的下降。例如小程序新版本发布后,即使各阶段耗时都下降,下载比例的升高反而可能导致总耗时的上升。
3. 影响打开率的因素
启动性能和用户的等待意愿是影响打开率的两个关键因素。在部分场景下,如果用户等待意愿较低,即使启动耗时很低,也不一定能获得较高的打开率。
运行时性能
setData
setData
是小程序开发中使用最频繁的接口,也是最容易引发性能问题的接口。在介绍常见的错误用法前,先简单介绍一下 setData
背后的工作原理。
工作原理
小程序的视图层目前使用 WebView 作为渲染载体,而逻辑层是由独立的 JavascriptCore 作为运行环境。在架构上,WebView 和 JavascriptCore 都是独立的模块,并不具备数据直接共享的通道。当前,视图层和逻辑层的数据传输,实际上通过两边提供的 evaluateJavascript
所实现。即用户传输的数据,需要将其转换为字符串形式传递,同时把转换后的数据内容拼接成一份 JS 脚本,再通过执行 JS 脚本的形式传递到两边独立环境。
而 evaluateJavascript
的执行会受很多方面的影响,数据到达视图层并不是实时的。
常见的 setData 操作错误
1. 频繁的去 setData
在我们分析过的一些案例里,部分小程序会非常频繁(毫秒级)的去setData
,其导致了两个后果:
- Android 下用户在滑动时会感觉到卡顿,操作反馈延迟严重,因为 JS 线程一直在编译执行渲染,未能及时将用户操作事件传递到逻辑层,逻辑层亦无法及时将操作处理结果及时传递到视图层;
- 渲染有出现延时,由于 WebView 的 JS 线程一直处于忙碌状态,逻辑层到页面层的通信耗时上升,视图层收到的数据消息时距离发出时间已经过去了几百毫秒,渲染的结果并不实时;
2. 每次 setData 都传递大量新数据
由setData
的底层实现可知,我们的数据传输实际是一次 evaluateJavascript
脚本过程,当数据量过大时会增加脚本的编译执行时间,占用 WebView JS 线程,
3. 后台态页面进行 setData
当页面进入后台态(用户不可见),不应该继续去进行setData
,后台态页面的渲染用户是无法感受的,另外后台态页面去setData
也会抢占前台页面的执行。
图片资源
目前图片资源的主要性能问题在于大图片和长列表图片上,这两种情况都有可能导致 iOS 客户端内存占用上升,从而触发系统回收小程序页面。
图片对内存的影响
在 iOS 上,小程序的页面是由多个 WKWebView 组成的,在系统内存紧张时,会回收掉一部分 WKWebView。从过去我们分析的案例来看,大图片和长列表图片的使用会引起 WKWebView 的回收。
图片对页面切换的影响
除了内存问题外,大图片也会造成页面切换的卡顿。我们分析过的案例中,有一部分小程序会在页面中引用大图片,在页面后退切换中会出现掉帧卡顿的情况。
当前我们建议开发者尽量减少使用大图片资源。