微信小程序性能优化实践
三个月前接手一个小程序项目,用户量大,交互复杂,性能一般。想法设法做了各种优化,取得了不错的效果,也在过程中收获了一些经验。昨天在公司内部做了一个技术分享,总结了一些优化经验,顺便整理为本文。 提高加载性能 典型的web类的应用,跑起来都需要3步: 第一步,加载运行环境; 第二步,下载代码; 第三步,执行代码,渲染页面。 小程序也如此。第一步加载运行环境,是微信实现的,开发者无需优化。 第二步下载代码,减少首次下载的包的大小,可提高速度。代码压缩、分包加载、预加载等操作,web应用需要借助webpack等打包工具才能实现,而小程序只需修改配置就行了,方便很多。 注意,subpackages配置路径外的目录将被打包到 app(主包)中。原项目在根目录下存了全局组件、样式、图片,导致主包非常大,一度逼近主包大小上线2M。这次把分包里的才会用到的组件,拆到分包所在的文件夹中;把图片资源放到CDN中。这样主包中只留下主包用拿到的代码和组件: [图片] 如果图片资源不多,可以考虑放在代码里,方便管理。但如果图片资源较大,建议使用CDN,这样图片就是在第三步(渲染页面)时才下载,而不是在第二步下载代码时一起下载,能够更快显示骨架屏,优化用户体验。 [图片] 第三步执行代码,优化项包括骨架屏、接口时序调整、懒加载等。其他优化方向还包括,使用数据预拉取,在下载代码阶段提前获取业务数据。这个跟业务高度相关,此处就不展开细讲。 控制setData数据量 setData是小程序开发中使用最频繁的接口,也最容易引发性能问题。每次setData都会触发页面的重新渲染,如果渲染量计算量过大,很容易造成页面卡顿,影响用户体验。原理可以参考官方文档,这里只说实践:不要频繁setData,每次setData数据量不要太大。下面举两个例子。 前端经常会遇到"超长的列表"的难题。因业务需求,后台返回的数据不做分页,一个列表几百甚至上千项,如果直接通过setData写进去,页面一下子就卡死了。优化方案是做前端的分页加载:收到数据后把全部数据存在一个变量里,只取第一页的数据setData更新页面。等用户下拉触发更新的时候,再继续setData下一页的数据。 长度实在太大的情况下,卡顿不再仅仅是setData的问题,而是节点过多导致占用内存过大,这时还可以试下循环列表。 另一个例子是两个列表的数据对比。先说下业务背景:先查商品列表,再查购物车列表,如果该改商品的在购物车列表中有数据,则要更新列表上的数据。之前的做法一直都是循环一遍对比列表,再整个列表数据进行setData,当购物车数量越来越多的时候,就开始卡死了。这次优化引入了Worker,每次购物车更新的时候,在Worker中进行diff运算,算出需要更新列表的哪几项,再进行setData,大大减少了setData的数据量,性能有了明显的改善。 其他细节优化 响应客户滑动事件的需求,使用WXS。之前是把页面touchmove事件绑到js中的逻辑,这样会导致页面的响应不够及时。这次优化把滑动相关的事件都做到wxs里,滑动的体验大大改善。原理涉及小程序的框架视图层(Webview)和逻辑层(App Service)通信机制,官方文档有详细说明。 适当选择同步或异步API。小程序里有很多同步的Api(结尾带Sync的都是),都是阻塞性的。举个例子,常用的wx.getStorageSync()至少消耗50ms运行时间,如果是游戏等性能敏感的项目,卡顿大约3帧。积少成多,用户体验的差异就很明显了。能用异步的地方,尽量不要偷懒用同步的API。 还有一些代码逻辑优化,算法优化等,此处不再展开细讲。推荐一本老书《高性能JavaScript编程》。 总结 以上优化思路,并不局限于微信小程序。小程序的原理和web高度相似,很多优化经验,都可以和web互相借鉴参考。个人总结的三大优化原则:1.使用合理的技术架构;2.养成良好的编码习惯;3.遇到瓶颈之前不要瞎优化。 这两年来小程序生态蓬勃发展,追加了许多实用的功能,开发配套也日益完善。跨页面数据通信可以用Omix,做多端同构用kbone,开发体验比以前有了很多的改善。现在越来越多的产品选择微信小程序平台,体验好、文档完善、兼容性不错、学习曲线平滑、容易找工作,非常推荐新手入坑。 [图片]