- 了解小程序的启动流程(上)
[视频] *所有课程源码的链接:https://gitee.com/geektime-geekbang_admin/weapp_optimize 你好,我是李艺,是腾讯云TVP 、小程序从0到1的作者,极客时间 微信小程序全栈开发实战课程讲师。 小程序上线已经5年时间了,日活目前已经达到了4.5亿+,已然成为任何一家互联网企业都不能忽视的产品运营阵地。小程序的开发能力经过微信团队数年来的不断地努力,目前已经日臻完善,它早已经不是那个随随便便翻翻文档就可以完成开发的一个简易框架了,尤其是在性能优化方面,会优化与不会优化 ,对于产品的运行效果可以说有霄壤之别。 首先我们看第一部分,需要明确一下有哪些需要优化的现象。不知道你的小程序产品有没有遇到过这样的一些问题,点开小程序一直都是白屏什么也看不到、Loading加载提示转了好几圈页面还不显示,单击页面链接的时候页面跳转迟钝迟迟打不开、有的按钮单击了好几次一点反应也没有,长列表内容在滑动的时候越往下滑 页面越卡顿。你有没有因为这些问题而遭受过用户的抱怨,你会以为这些问题都是因为平台技术不完善而造成的吗? 那么为什么京东 滴滴等大厂的一些小程序,它们的功能那么繁杂。但使用起来却还是那么流畅呢,当我们抱怨框架不够给力的时候,我们对微信小程序的性能优化技巧又真正了解和使用多少?性能优化它是一个现人现地的活,讲究具体问题具体分析,需要有一个字节 一个字节去抠,一个毫秒 一个毫秒去节省的这样的一个细致精神。这个课程我们会演示相关的性能优化技巧。我准备了一个性能比较堪忧的项目,这个课程我们就一起诊断 优化这个项目,让它从体态臃肿的一个状态慢慢变得健步如飞,为了更好地理解和应用小程序优化技巧,在开始实践之前,我们十分有必要看一下小程序整体的运行环境以及启动的流程。小程序的运行环境大体可以分为三类,第一类是iOS端、Mac微信端,第二类是Android端 PC微信端,第三类就是我们开发者经常使用的微信开发者工具模拟器端。另外还有儿童手表上面也有微信,但是那个环境它没有小程序,所以不在我们的讨论范围之内。 三类的运行环境,虽然它们在底层是基于不同的技术实现的,但是它们的启动流程大体上是相似的,小程序的优化主要是指从小程序开始启动到首页完全渲染显示,也就是Page.onReady事件派发,这个过程之间的一个优化。这个过程主要包含了三个流程的节点,这一步包括小程序运行进程及运行环境的准备,这里面具体又包括拉取小程序基本信息,包括代码包版本 地址等信息,另外还有Native小程序进程和微信基本模块的一个初始化。例如在Android环境里面有Activity活动组件的一个初始化,再往下是代码包的下载 校验以及初始化,再往后是系统组件 WebView组件容器和原生组件的一个初始化,最后是JS引擎初始化以及域的创建。 下面我们看第二步关于代码注入,这一步主要包含两大部分:第一部分是框架及第三方基础代码的一个初始化,这里面又分为三个小部分: 第一部分是小程序基础库的注入; 第二小部分是扩展库,例如我们在配置文件里面通过使用useExtendedLib引入的WeUI以及kbone这样的一个类库的初始化; 第三小部分是插件、自定义组件 扩展库代码的一个注入。 第二部分是开发者代码的一个注入,这个里面主要分为两个小部分: 第一个小部分是开发者逻辑层代码的一个注入,这里会派发小程序里面的App.onLaunch还有App.onShow这些事件的一个派发,这些事件都是在这个阶段进行派发的; 第二小部分是开发者视图层代码的一个注入,包括公共代码以及页面代码的一个注入。 下面我们看第三部分关于首屏渲染,这个部分大致可以分为五个小部分: 第一小部分是页面的初始化,这个时间点是initDataSendTime这个时间点的一个触发时机,会有Page.onLoad一个事件的派发; 第二小部分是时间点走到viewLayerReaderStartTime这样的一个时间点的阶段,这个时候会有Page.onShow事件的一个派发; 第三小部分是开发者代码从后端拉取数据,准备data数据,这个时候也是一个阶段,是第三小部分; 第四小部分是页面的一个整体的渲染; 第五部分是当这个时间点走到viewLayerReaderEndTime这个时间点的时候,它会有一个Page.onReady事件的派发,这个时候就标志着我们首屏渲染的一个完成。 小程序采用逻辑层、视图层双线程运行机制,Native的工作准备它是先于这两个线程开始之前开始的,基础的执行环境准备好以后,逻辑层与视图层两个线程才开始工作,并且两个线程几乎是并发执行的。在视图层与逻辑层它代码完全注入以后,这个时间点它会对齐以后才会进入下一个阶段,也就是首屏渲染这个阶段的开始执行。 这些节点它并不是每一次小程序启动时都会经历的,有些会有,有些不会有。微信有运行环境预加载机制,如果小程序在启动时命中了预加载的环境,有关准备运行环境的节点就可以省略掉,这一部分的启动时间也可以节省了。对于开发者紧跟小程序框架的更新,及时使用用户覆盖率最广的基础库版本,让自己的小程序运行环境大众化、普通化,则有助于预加载环境的一个命中,终端类型不同经历的节点也不尽相同。 在Android上小程序启动的时候,微信它开启了新线程,在iOS上则没有 iOS上小程序它在启动的时候,它会复用与微信相同的一个进程,因此Android上有小程序进程与Activity初始化这样的一个节点,在iOS上则没有,再加上iOS的设备它普遍的性能是高于Android设备的,所以这使得iOS的设备的启动的效率普遍就高于Android。 对于相同版本的小程序在同一性能级别的设备上运行,iOS设备平均会比Android大概会少0.5的这样一个启动时间,另外还有启动方式对流程经历的节点也有影响。 下面我们看一下启动方式。小程序按启动方式不同分为冷启动和热启动两种方式。 什么是冷启动?什么是热启动?如果小程序在用户设备上是第一次打开或者是销毁后再次打开,这个时候的启动就是冷启动。热启动是相对冷启动而言的,热启动是小程序启动的一种优化机制,小程序进入后台30分钟以内再次进入前台,可以直接从后台状态然后恢复到前台,在这种热启动方式里面,像前面我们提到的小程序基本信息、拉取代码包的下载还有JS引擎初始化等等这些流程节点,甚至像App.onLaunch、Page.onLoad以及Page.onReady这些一次性的流程事件都不会有了。小程序第一次启动以及冷启动30分钟以后被系统回收重新再启动都是冷启动。 前面我们讲的启动流程的主要节点是冷启动流程的节点。我们说的小程序性能优化主要是指冷启动性能的一个优化以及运行时渲染性能的一个优化,在小程序冷启动流程里边涉及到一些程序以及页面事件。下面我们统一看一下这些事件。 在小程序中App与Page都有它们各自的一个生命周期函数,这些周期函数有一些与启动流程是密切相关的。我们先看一下App周期函数,这里面有三个事件需要我们注意: 第一个是onLaunch,它是监听小程序初始化的一个事件; 第二个是onShow 监听小程序启动或切前台这样一个事件; 第三个是onHide 监听小程序切后台这样的一个事件。 下面我们再看一下Page周期函数。这个里面有五个事件是与优化相关的: 第一个是onLoad它监听页面加载; 第二个是onShow监听页面显示; 第三个是onReady监听页面初次渲染完成; 第四个是onHide监听页面隐藏; 第五是onUnload监听页面卸载。 App.onShow事件和Page.onShow事件是视图界面开始显示时派发的,它们会重复派发与启动流程优化密切相关的一次性事件,主要有App.onLaunch Page.onLoad和Page.onReady这三个事件,在这三个事件节点恰当的安排执行合适的逻辑代码是优化的重要技巧一。 至于像App.onShow App.onHide以及Page.onHide Page.onUnload是与运行时性能优化十分相关的一些事件,下面我们根据小程序的冷启动流程以及与其相关的密切相关的一些八个生命周期函数大致讲一下有哪些节点是可以优化的。 第一条在这个环境准备阶段中,在拉取小程序基本信息阶段,这个阶段是有可能优化的。微信对用户设备上经常使用的小程序它会有轮询机制,在轮询的时候会自动拉取小程序的一个基本信息,正常情况下这个小程序的基本信息的一个拉取它是同步的,它会阻塞我们后续流程节点的一个执行,如果通过轮询节省了这样的一个过程,启动流程跳过这个节点时间是可以节约的,当然这个节点开发者基本上做不了什么事情,开发者并不能左右微信的轮询机制。但是越受用户欢迎的一个小程序因为它属于经常使用的小程序,它会命中轮询机制,启动的一个性能也会更好,而那些不被用户经常访问的小程序反而没有这个福利,这大概就是技术里面的一个马太效应,就是好的会更好然后坏的会越差。 针对环境准备阶段微信提供了环境预加载机制,微信客户端会根据用户设备的使用场景和设备资源的一个消耗情况,依据一定的一个策略,在小程序启动之前对运行环境进行部分的预加载,这个过程开发者基本也无法干涉,开发者能做的仅是紧跟小程序基础库的一个更新,积极使用最新的、最普遍的、最广泛的一个基础库版本以及提高预加载环境的一个命中率。 在代码注入阶段,逻辑层与视图层代码都需要注入,两个线程的代码都注入完成以后首屏渲染流程才能开始,Page.onLoad事件才能触发。我们可以想方设法减少代码的一个注入量和复杂度以期减少启动时间,小程序在这方面有分包、有独立分包、有按需注入、有用时加载和占位组件等等这些特性,这些都是这一阶段的一些优化技巧。这些技巧稍后我们在课程里面都会详细介绍。 在合适的生命周期函数节点执行合适的代码也可以优化启动性,Page.onReady事件派发于首屏渲染完成的时候,如果我们要从后端拉取数据并在首页上进行渲染,在这个事件函数里面执行拉取操作,势必会造成二次渲染的CPU资源浪费,但如果我们在Page.onLaunch这个事件触发的时候就开始数据拉取,又可能会阻塞小程序正常的一个启动流程,在这种情况下我们要怎么去做?我们可以使用异步转同步的编程范式以及使用并发复合命令,在多个文件里边对齐这个代码的执行点,这样的话就显得尤为重要了。具体的优化办法,稍后我们在课程里面会详细讲解。 从Page.onLoad事件派发页面开始渲染到Page.onReady这个事件派发首屏渲染完成,这中间涉及到的动态数据加载,其加载的数据量有多少、网络请求所需的时间有多少还有图片等静态资源它加载所需要的时间有多少,都会影响首屏渲染的一个效率,这个阶段使用骨架屏技巧包括压缩图片、提高服务器接口响应效率和数据传输效率等等,这些都可以优化首屏渲染的一个用户体验。针对小程序里面用到的一些数据,微信还提供了数据预加载周期性更新机制,不需要开发者自己去拉取微信就可以代为拉取,小程序在启动的时候,直接取用这些已经加载好的数据就可以了,这也是优化启动流程的一个技巧之一。 当然了这个技巧是微信团队特意为开发者而设计的,针对低端机首次渲染需要较长的一个时间,微信提供了初始渲染缓存机制,启用初始渲染缓存可以使视图层不需要等待逻辑层代码初始化完毕就可以直接提前将这个页面初始化的数据渲染的结果展示给用户。 以上就是针对启动流程中部分节点的一个性能优化技巧,稍后我们在课程里面都会详细地进行讲解在运行的时候针对小程序的双线程运行机制和视图重渲染机制也有相关的一些性能优化技巧。下面我们就再看一下这方面的一些技巧。
2022-07-29 - 大图预览下添加图片描述,到底该怎么办呢?
前言 产品说什么也要在大图预览下加图片描述,我说微信小程序不支持,wx.previewImage和wx.previewMedia都是我们自己改不了的。但是无奈非得要,那我说:加可以,但是做不到像wx.preview那样完美,右上角会有胶囊按钮,其它体验也会也些差距。为了加这个图片描述,我是抽业余时间搞了好多天才搞出来,真是。。。 示例动图 [图片] 实现思路和方案: 将navigationBar隐藏掉,然后黑色背景一搞,左右切换使用swiper。因为考虑到swiper加载item太多会有渲染问题,我们在这里使用之前写的库swiper-limited-load。图片使用movable-view来实现双指缩放和移动功能,此外图片还应该有双击缩放,单击退出等功能视频使用video组件,要考虑到只有滑动到当前item,才去渲染当前item的video组件,要不然出现左右两个video也跟着一起播放的情况就尴尬了。视频要实现宽度铺满,按宽高比例显示,需要知道视频的宽高比,这里可以用wx.getImageInfo来获取视频封面图片的信息(网络图片需要配置download域名),或者如果你们的接口会返回视频的宽高信息,根据屏幕宽度,直接设置高度也行。总结 微信自带的wx.previewImage和wx.previewVideo其实已经挺好用了。就为了一个图片描述,我们自己造这么个轮子,得好几天时间,而且这个轮子还不如原来的好用。面对这种情况,这就看是要如何取舍了,是要开发效率,还是要用户体验。既然产品需要,那就硬刚吧。。。 项目地址:https://github.com/pengboboer/preview-media-desc 如果错误,欢迎指出。 如有新的需求也可以提出来,如果有时间的话,我会帮你们完善。 如果能帮到你们,记得给一个star,谢谢。
2020-09-24 - 小程序实现图片倒影?真机无效果
使用-webkit-box-reflect,开发工具有效果,真机没有效果[图片][图片]
2021-01-06 - 请问如何批量上传300+个微信小程序?
我公司是软件服务商,服务客户几百个,几百个微信小程序 请问微信有没有什么接口,能够直接帮助用户打包上传发布小程序的接口呀?
2022-02-27 - 小程序太多如何批量发布
公司专做小程序,一个小程序代码可能给很多客户使用,就会有很多小程序 怎么把这些小程序一次提交审核。 如果不一次提交审核,可能有问题,如有的客户小程序审核成功,接口服务就要升级到最新,但有的客户小程序还没有升级,这样会导致没升级客户小程序不能使用
2018-02-28 - wx.requestSubscribeMessage 小程序模版消息升级为订阅消息,
还要从那不久前的炎炎夏日说起, 一位苦逼的前端小妹, 为了加模版消息,熬了好几个加班夜, 动了几十个页面, 修改了几百个按钮, 终于把模版消息都全面埋雷, 不留任何死角. 也就过了才 1 2 3 4 5个月吧, 订阅消息一出. 我们的前端小妹, 那脸色、那眼神、我至今找不到一个合适的词语来形容(主要是笔者词穷) 下面还是主要来说说订阅消息吧, 不然对不起读者. 升级第一步: 注意订阅消息是有最低版本库要求的 (这个主要是需要产品和客户同步, 不是所有人都能订阅哦) 注意:iOS客户端7.0.6版本、Android客户端7.0.7版本之后的一次性订阅/长期订阅才支持多个模板消息,iOS客户端7.0.5版本、Android客户端7.0.6版本之前的一次订阅只支持一个模板消息 升级第二步: 干就完了 官方 api 地址: https://developers.weixin.qq.com/miniprogram/dev/api/open-api/subscribe-message/wx.requestSubscribeMessage.html wx.requestSubscribeMessage(Object object) [图片] 撸起袖子就是干 小手一抖, 代码全有 [图片] 屏幕一点, 效果立显 [图片] 友情提示: 这里 tmplIds 用的是订阅消息 id 哦, 不要搞错咯 这里必须是在手机上才能看到效果哦 每次弹框, 只能配置最多 3 个订阅消息哦 如果勾选了: “总是保持以上选择, 不再询问” , 真的就是“此生不复相见哦”, 删除了小程序也不管用哦 由于弹出的 3 个订阅消息, 是可以单独勾选, 就会出现如果某 1 个配置的已经“总是保持以上选择, 不再询问”. 那么弹框只会显示其他两个哦, 属于正常情况. 不要以为是哪里错了哈. 并且返回的结果还是 3 个(不要晕哈, 说的啰嗦, 其实不难理解) 小框框弹出来了, 返回也很顺利拿到了, 抿一口手边的枸杞菊花茶, 是不是很舒服? 上面说到了, “总是保持以上选择, 不再询问” , 就是“此生不复相见哦”, 那么如果之前手贱, 点了拒绝. 那如何才能重新订阅呢? 小生也是研究了的: 操作步骤: 右上角点点点, 》 设置 》订阅消息 效果一目了然 [图片] 前方高能: 设置里的订阅消息, 它此生的标签是 “总是保持以上选择, 不再询问”, 不管是你允许还是拒绝, 都不会在弹框里再看到 写在最后 提一个更苦逼的事情, 记得把之前为获取 formid 而写的代码, 统统删掉 写在最最后 给不给点赞? 不点我下一篇还问 未完待续… 以下是补充哦, 持续关注订阅消息 一: 一个模版, 在首页勾选了“总是保持以上选择, 不再询问”按钮. 在别的页面也将不会有弹框. 你懂的, 在产品角度这个是很重要、很关键的交互需求 二: 同意次数是可以累计的. 也就是说, 一个模版, 客户A点击了 10 次允许发送消息. 那我们就可以给他发 10 次模版消息提醒 三: 一次拒绝, 是不会清除之前同意所累计的次数的 这个是针对有网友说: “点一次同意, 再点击一次拒绝,是收不到消息的”. 实践证明: 点一次同意, 就能发一次消息, 后面点击拒绝, 不影响之前点击同意的 四: 有网友问: ”一个弹框有三个模版, 全都勾选并同意. 可以发几条消息? “ 很明显是三个模版每个可以发一次. 这个也是验证了的 干活!! 是不是满满的都是干活!
2019-12-09