• 乐玩联盟小程序的性能优化之路


    乐玩联盟小程序开发者:本文阅读时长约 10 分钟,都是干货~

    小程序背景

    乐玩联盟小程序自去年上线之后,本人就定下一个目标‘有App样的精致体验’,这对于一个人开发乐玩小程序来说,无疑是个挑战。

    为了达成目标,“页面性能”、“友好的产品体验” 和 “稳定的系统服务” 成为了本人最基本执行原则。

    首页作为乐玩小程序的门脸,其性能表现和用户留存率息息相关。因此,2020年初我对乐玩首页进行了一次全方位的升级改造,从加载、渲染等维度深挖小程序的性能可塑性。

    除此之外,为了提高研发效率,在公司增加新需求的同时,不断地优化改造,如今的乐玩联盟小程序可以说是焕然一新。

    如何定义高性能?

    提起高性能,大家都会说:“页面加载足够快”。似乎加载速度成了高性能的标准,其实只是加载快还不够。

    想一想,页面很快加载出来,但是轮播图卡顿,搜索框无效,页面排版不统一无美感,上拉卡顿,想想这些足够让用户流失。所以,单考虑加载速度是远远不够了。

    小程序后台性能分析

    微信小程序官方也有性能指标:

    • 首屏时间不超过 5 秒;
    • 渲染时间不超过 500ms;
    • 每秒调用 setData 的次数不超过 20 次;
    • setData 的数据在 JSON.stringify 后不超过 256kb;
    • 页面 WXML 节点少于 1000 个,节点树深度少于 30 层,子节点数不大于 60 个;
    • 所有网络请求都在 1 秒内返回结果;

     

    这些数据,大家可以通过开发者工具体验评分工具(`Audits` 面板)体验评分,按照给出的优化建议,针对性的调整

     

    第二,我们还可以根据小程序管理平台小程序助手网络性能这三个维度分析数据

    通过这些辅助工具,我们可以根据客户端系统机型网络环境访问来源等条件做精细化的分析,还是很有参考价值的

    乐玩联盟小程序性能分析

    1,小程序启动太慢

     

    一,分析原因:

    在这个阶段,小程序要(包括启动前后的时机),微信会默默完成下面的几项工作:

    1. 准备运行环境:

    2. 下载小程序代码包:

    3. 加载小程序代码包:

    4. 初始化小程序首页:

    这一步,关键就是控制小程序包的大小,这样可以有效的缩短下载时间(控制包的大小能非常直观的感受到小程序性能提升)

    二,控制包的大小,常用的方法就是:

    1. 无用文件,函数,样式的剔除:

    2. 减少代码包中的静态资源文件:建议图片,视频等静态资源都放在CDN上

    3. 逻辑后移,精简业务逻辑:一般不涉及到前端计算的展示类逻辑,都可以适当做后移。这招要看你和后端同学商量了,给他们提改造需求,小心分分钟被打(开个玩笑)...不过这样真的能节省很多前端代码量,而且很多时候,上线后发现什么问题。还可以后端直接解决了,不用提审,再发布

    4. 复用模板插件:

    5. 分包加载,部分页面h5化

    2,白屏时间

    启动这段时间的白屏,主要由两个元素构成:

    一,分析原因:

    1. 网络资源加载时间:

    2. 渲染时间:

    二,有什么办法解决呢?

    1. 启动本地缓存:可以在用户访问页面时,优先从缓存里面取上一次接口请求回来的数据,待网络请求完毕时再覆盖(但是要注意,有些及时性的数据就行不通了,还是要看使用场景),乐玩小程序还没有使用到这。用wx.getBackgroundFetchData微信提供的客户端缓存数据方案。官方文档https://developers.weixin.qq.com/miniprogram/dev/api/storage/background-fetch/wx.getBackgroundFetchData.html

    2. 分时渲染:通过延迟非关键元素的渲染时机,为关键渲染路径腾出资源。

    可以看到今日上新板块是被故意延后渲染,这样空出资源渲染banner图片(乐玩联盟小程序banner图张较多)

    3. 图片使用webP格式:Google 推出的一种支持有损/无损压缩的图片文件格式,有资源的同学可以使用

    4. 图片裁剪&降质:乐玩小程序使用的是阿里云的OSS

    5. 图片懒加载、雪碧图(CSS Sprite)优化:乐玩首页的二级菜单就是用到雪碧图,图片懒加载小程序img标签有  lazy-load="true"

    6. 降级加载大图资源:在乐玩中,几乎全部大图都用到这一方法(参看首页banner)(我们可以先呈现高度压缩的模糊图片,同时利用一个隐藏的 <image> 节点来加载原图,待原图加载完成后再转移到真实节点上渲染。)

    <!-- banner.wxml -->
    <image src="{{url}}" />
    
    <!-- 图片加载器 -->
    <image
      style="0;height:0;display:none"
      src="{{preloadUrl}}"
      bindload="onImgLoad"
      binderror="onErrorLoad"
    />
    methods: {
        onImgLoad() {
          this.setData({
            url: this.originUrl                       // 加载原图
          })
        }
      }

    以上是图片降级加载的关键代码(注意,具有 display: none 样式的 <image> 标签只会加载图片资源,但不渲染。

    7. 骨架屏:从用户感知角度添加了骨架屏。‘白屏’带来的用户体验非常难受,在乐玩联盟小程序中,使用了尺寸固定的骨架屏,来减少数据渲染带来的页面结构不稳定情况(这样有一个缺点就是维护成本高,首页样式布局改变,要更新骨架屏样式)

     <!-- 骨架屏 -->
        <block v-if="showSkeleton">
          <div class="wrap">
            <div
              v-for="(item,index) in skeletonRectLists"
              :index="index"
              :key="item"
              class="chiaroscuro"
              :style="{'width':item.width+'rpx','height':item.height+'rpx','background-color':'rgba(233, 2, 233,1)','position':'absolute','left':item.left+'rpx','top':item.top+'rpx'}"
            ></div>
            <div
              v-for="(item,index) in skeletonCircleLists"
              :index="index"
              :key="item"
              class="chiaroscuro"
              :style="{'width':item.width+'rpx','height':item.height+'rpx','background-color':'rgba(233, , 233,1)','border-radius':item.width+'rpx','position':'absolute','left':item.left+'rpx','top':item.top+'rpx'}"
            ></div>
          </div>
        </block>
    data:{
       return{
        showSkeleton: true, //首页骨架屏
        skeletonRectLists:[ // 方形骨架屏数据
            {72,height:48,left:40,top:100} ,
            ...... 
        ],
      skeletonCircleLists:[ // 圆形骨架屏数据
          {136,height:136,left:7,top:476} ,
          ...... 
      ],
    } }
    // 骨架屏样式
    .wrap {
      position: absolute;
      left: 0;
      top: 0;
      z-index: 9998;
      overflow: hidden;
      width: 750rpx;
      height: 1460rpx;
      background-color: #fff;
    }
    .chiaroscuro {
      animation-duration: 1s;
      animation-fill-mode: forwards;
      animation-iteration-count: infinite;
      animation-name: placeHolderShimmer;
      animation-timing-function: linear;
      background: #f6f7f8;
      background: linear-gradient(to right, #eeeeee 8%, #dddddd 18%, #eeeeee 33%);
      background-size: 800px 104px;
      height: 40px;
      position: relative;
      border-radius: 6px;
    }
    @keyframes placeHolderShimmer {
      0% {
        background-position: -468px 0;
      }
      100% {
        background-position: 468px 0;
      }
    }

     数据加载完毕后改变showSkeleton为false(隐藏骨架屏

    回收后台页面计时器

    这一步在乐玩小程序中特别关键,乐玩小程序有相当多的页面需求要用到setIntervalsetTimeout

    在高峰时期,一个页面同时会需要运行十个计时器,所以在页面(组件) onHide 时一定要手动清理掉,并且在 onShow 时恢复定时器,一个定时器的回调 setData 是微不足道的,但也是不可忽视的

    避免频发事件中的重复内存操作

    1,onPageScroll 事件回调使用节流:参考函数节流 Throttle

    2,避免 CPU 密集型操作,譬如复杂的计算;

    3,避免调用 setData,或减小 setData 的数据量:delete 无用的数据

    4,尽量使用 IntersectionObserver[24] 来替代 SelectorQuery[25],前者对性能影响更小;

    总结

    通过以上问题的分析并解决,乐玩小程序性能得到了很大的提升。这也要感谢京喜小程序团队的技术分享,参考链接https://mp.weixin.qq.com/s/nXModRImp4H7iisMQSc2Wg

    基于小程序的底层架构原理,研究小程序的性能之路还很漫长,本人将继续在研究性能、提升体验这条路上砥砺前行。

    最后希望这次分享能给您带来一点参考价值。

  • 相关阅读:
    Abp Swagger API中文说明配置方法
    ABP框架中使用MySQL数据库
    windows + jenkins + .net core + iis自动化部署新手入门
    在图片上画矩形框
    base64转换成np、opencv、PIL
    RankSVM
    tf.placeholde函数解释与用法
    slim.arg_scope()的使用
    SSD网络结构
    tensorflow学习笔记
  • 原文地址:https://www.cnblogs.com/Webzhoushifa/p/12692910.html
Copyright © 2020-2023  润新知