百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

微信小程序性能优化汇总

bigegpt 2025-03-06 12:24 8 浏览

示例简介

本文介绍如何对微信小程序进行性能优化,下面内容将从两大方面进行分析总结:

1、工具的使用;

2、常见的优化方向;

工具的使用

1、使用微信小程序自带的工具插件“体验评分”,运行环境的要求和使用流程参考“
https://developers.weixin.qq.com/miniprogram/dev/devtools/audits.html”;最终运行效果如下图:

2、然后根据效果图的分析报告,查看需要优化的细项(里面都有详细的问题描述和优化路径说明),并根据说明一一进行优化:

常见的问题包括:

1)应避免出现任何JavaScript异常:

因为出现JavaScript异常可能导致小程序的交互无法进行下去;

2)小程序所有请求响应正常:

因为请求失败可能导致小程序的交互无法进行下去;

3)所有请求的耗时不应太久:

因为请求耗时太长会让用户一直等待甚至离开,应当优化好服务器处理时间、减小回包大小,让请求快速响应;

4)避免将未绑定在 WXML 的变量传入setData:

因为setData操作会引起框架处理一些渲染界面相关的工作,而一个未绑定的变量意味着与界面渲染无关,传入setData会造成不必要的性能消耗;

5)合理设置可点击元素的响应区域大小:

因为过小会导致用户很难点中,体验很差;

6)避免渲染界面的耗时过长:

因为渲染界面的耗时过长会让用户觉得卡顿,体验较差,出现这一情况时,需要校验下是否同时渲染的区域太大;

7)避免执行脚本的耗时过长:

因为执行脚本的耗时过长会让用户觉得卡顿,体验较差,出现这一情况时,需要确认并优化脚本的逻辑;

8)对网络请求做必要的缓存以避免多余的请求:

因为发起网络请求总会让用户等待,可能造成不好的体验,应尽量避免多余的请求,比如对同样的请求进行缓存;

9)wxss 覆盖率较高,较少或没有引入未被使用的样式:

按需引入 wxss 资源,如果小程序中存在大量未使用的样式,会增加小程序包体积大小,从而在一定程度上影响加载速度;

10)文字颜色与背景色搭配较好,适宜的颜色对比度更方便用户阅读;

11)所有资源请求都建议使用 HTTPS:

因为使用 HTTPS,可以让你的小程序更加安全,而 HTTP 是明文传输的,存在可能被篡改内容的风险;

12)不使用废弃接口:

因为使用即将废弃或已废弃的接口,可能导致小程序运行不正常。一般而言,接口不会立即去掉,但保险起见,建议不要使用,避免后续小程序突然运行异常;

13)避免过大的 WXML 节点数目:

建议一个页面使用少于 1000 个 WXML 节点,节点树深度少于 30 层,子节点数不大于 60 个。一个太大的 WXML 节点树会增加内存的使用,样式重排时间也会更长;

14)避免将不可能被访问到的页面打包在小程序包里:

因为小程序的包大小会影响加载时间,所以应该尽量控制包体积大小,避免将不会被使用的文件打包进去;

15)及时回收定时器:

因为定时器是全局的,并不是跟页面绑定的,所以当页面因后退被销毁时,定时器应注意手动回收;

16)避免使用 css ':active' 伪类来实现点击状态:

使用 css ':active' 伪类来实现点击状态,很容易触发,并且滚动或滑动时点击状态不会消失,体验较差;建议使用小程序内置组件的 'hover-*' 属性来实现;

17)滚动区域可开启惯性滚动以增强体验:

因为惯性滚动会使滚动比较顺畅,在安卓下默认有惯性滚动,而在 iOS 下需要额外设置
-webkit-overflow-scrolling: touch 的样式;

常见的优化方向

总结一些经常会出现问题的地方,并介绍可以使用的解决方法;

1、启动加载性能优化:

11、控制代码包大小:

勾选开发者工具中"上传代码时自动压缩";

及时清理无用代码和资源文件;

减少代码包中的图片等资源文件的大小和数量;

12、分包加载:

将小程序中不经常使用的页面放到多个分包内,主包是保留最常用的核心页面;启动时只加载主包,使用时按需下载分包;

使用分包加载会出现用户首次进入分包页面时需要进行分包的下载和注入,造成页面切换的延迟;开发者可使用分包预下载,预先配置页面可能会跳转到的分包,框架在进入页面后根据配置进行预下载;

13、独立分包:

从分包页面启动时,需要先依赖于主包的下载和注入,启动速度受主包限制;使用独立分包,从独立分包页面启动,只要下载和注入分包就可以打开页面;

2、首屏加载的体验优化建议:

21、提前请求:异步数据请求不需要等待页面渲染完成(onLoad 阶段就可以发起请求,不用等ready);

22、利用缓存:利用storage API对异步请求数据进行缓存,二次启动时先利用缓存数据渲染页面,而下拉刷新或者缓存过期才更新数据;

23、避免白屏:先展示页面骨架和基础内容;

24、及时反馈:即时地对需要用户等待的交互操作给出反馈,避免用户以为小程序无响应;

3、避免不当使用setData:

31、存在setData的数据过大(通讯耗时与数据量相关,页面更新延期;使用setData的特殊key实现局部更新);

// 1: 初始一个list,存储列表数据
this.data = startList
// 2: 监听滚动事件,滚动到底部获取新数据,并追加到list尾部,最后重新setData
onReachBottom:()=>{
  const {list} = this.data
  fetchNewData().then((res)=>{
    list.push(res.list);
    this.setData({list})
  }
}

大部分人面对长列表滚动的时候,一开始的处理方式都是这样的,如果数据不多,只有几页可能不会太暴露问题;但当页数过多,几十页甚至上百页的情况,list的数据会越来越大,每次setData的数据就会越来越多,因而每次页面重新渲染的节点就会越来越多,从而导致滚动到后面,加载越来越慢。另外,由于小程序的视图渲染层和数据逻辑处理层是分开的,不是在同一个线程上面的,从用户触发页面交互,到处理数据逻辑,最后呈现页面,数据到视图是需要传输的,因而小程序本身对数据大小也有限制,不能超过1M。

我们可以通过数据路径的写法,来将数据分批的传输到视图层中,减少一次性setData的数据大小。具体写法如下:

// 1.通过一个二维数组来存储数据
let feedList = [[array]];
// 2.维护一个页面变量值,加载完一次数据page++
let page = 1
// 3.页面每次滚动到底部,通过数据路径更新数据
onReachBottom:()=>{
  fetchNewData().then((newVal)=>{
    this.setData({
      ['feedList[' + (page - 1) + ']']: newVal,
    })
  }
}
// 4.最终我们的数据是[[array1],[array2]]这样的格式,然后通过wx:for遍历渲染数据

32、列表局部更新:

比如,将点赞的id传过去,查找相对应id的那条数据的下标(index是不会改变的),用setData进行局部刷新

this.setData({
    list[index] = newList[index]
})

33、短时间内频繁调用setData:

因为会出现操作卡顿、交互延迟、页面渲染延迟等问题; 优化:避免不必要的setData,对连续setData调用进行合并;

34、避免后台态页面进行setData,因为后台态页面去setData也会抢占前台页面的执行

4、存在短时间内发起太多图片请求:

就是渲染页面时,一次性发送了过多的图片请求,导致了同一时间发起了过多的http请求,http连接是非常耗时的,尤其是一次性发起这么多,并且一次性发起的http链接也是有限制的,比如chrome浏览器就限制一次性最多6个。

所以在渲染页面时,不在视图范围内的图片我们不加载,只有元素出现在视图范围内了,再渲染。

常规的做法是,通过 getBoundingClientRect() 获取元素的位置,然后与页面滚动位置比较,如果出现在视图内,就将 img 显示。这种方式有2个问题:

1)getBoundingClientRect()方法调用本身容易引起页面重排;

2)监听滚动事件本身就频繁触发,虽然可以通过节流的方式来减少,但还是容易增加无谓代码处理;

微信提供了 IntersectionObserver 对象,IntersectionObserver 对象,用于推断某些节点是否可以被用户看见、有多大比例可以被用户看见。

通过这个api我们不用再主动去监听元素位置了,在页面渲染一开始,通过这个api指明需要监听的元素,系统会自动去监听了元素位置。

let data = list;

data.forEach((item,index)=>{
  this.createIntersectionObserver().relativeToViewport.observe(`.img-${index}`,res=>{
    if (res.intersectionRatio > 0){
      this.setData({
        item.imgShow:true
      })
    }
  })
})


intersectionRatio值大于0,说明元素出现在视图中了,重新setData数据,显示图片组件。

5、存在图片太大而显示区域过小:

这个问题就是指图片尺寸太大了,而页面上我们显示的尺寸又太小了,图片尺寸大,请求图片就越慢,导致页面渲染速度下降。

对于页面里面的图片,最好都把图片存储在cdn服务器上,一个是能充分利用cdn缓存来加快请求速度,另外一个就是cdn上能够将图片进行一定的处理,比如裁剪。我司就是通过cdn来响应图片处理,然后请求图片时告诉cdn服务器需要什么要的尺寸图片,由cdn服务器响应对应尺寸图片。

6、key值在列表渲染中的作用:

key值在列表渲染的时候,能够提升列表渲染性能,为什么呢?首先得想想小程序的页面是如何渲染的,主要分为以下几步:

1. 将wxml结构的文档构建成一个vdom虚拟数

2. 页面有新的交互,产生新的vdom数,然后与旧数进行比较,看哪里有变化了,做对应的修改(删除、移动、更新值)等操作

3. 最后再将vdom渲染成真实的页面结构

key值的作用就在第二步,当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率

key值如果不指明,默认会按数组的索引来处理,因而会导致一些类似input等输入框组件的值出现混乱的问题。

因而,在做list渲染时,如果list的顺序发生变化时,最好增加key,且不要简单地使用数组索引当做key。

7、避免不当使用onPageScroll:

只在必要的时候监听pageScroll事件;

避免在onPageScroll中执行复杂逻辑;

避免在onPageScroll中频繁调用setData;

避免频繁查询节点信息(SelectQuery);

8、canvas渲染:

分层绘制到不同canvas,不变的部分单独绘制到一个canvas,动态生成地绘制到一个canvs,最后再合入到一个canvas。

总结

上文总结的只是平时一些常见的问题,并不是全部的问题;且随着微信小程序基础库的升级,有些问题可能会被优化解决,但也可能会产生其他的新问题。

相关推荐

程序员请收好:10个非常有用的 Visual Studio Code 插件

一个插件列表,可以让你的程序员生活变得轻松许多。作者|Daan译者|Elle出品|CSDN(ID:CSDNnews)以下为译文:无论你是经验丰富的开发人员还是刚刚开始第一份工作的初级开发人...

PADS在WIN10系统中菜单显示不全的解决方法

决定由AD转PADS,打开发现菜单显示不正常,如下图所示:这个是由于系统的默认字体不合适导致,修改一下系统默认字体即可,修改方法如下:打开开始菜单-->所有程序-->Windows系统--...

一文讲解Web前端开发基础环境配置

先从基本的HTML语言开始学习。一个网页的所有内容都是基于HTML,为了学好HTML,不使用任何集成工具,而用一个文本编辑器,直接从最简单的HTML开始编写HTML。先在网上下载notepad++文...

TCP/IP协议栈在Linux内核中的运行时序分析

本文主要是讲解TCP/IP协议栈在Linux内核中的运行时序,文章较长,里面有配套的视频讲解,建议收藏观看。1Linux概述  1.1Linux操作系统架构简介Linux操作系统总体上由Linux...

从 Angular Route 中提前获取数据

#头条创作挑战赛#介绍提前获取意味着在数据呈现在屏幕之前获取到数据。本文中,你将学到,在路由更改前怎么获取到数据。通过本文,你将学会使用resolver,在AngularApp中应用re...

边做游戏边划水: 基于浅水方程的水面交互、河道交互模拟方法

以下文章来源于腾讯游戏学堂,作者Byreave篇一:基于浅水方程的水面交互本文主要介绍一种基于浅水方程的水体交互算法,在基本保持水体交互效果的前提下,实现了一种极简的水面模拟和物体交互方法。真实感的...

Nacos介绍及使用

一、Nacos介绍Nacos是SpringCloudAlibaba架构中最重要的组件。Nacos是一个更易于帮助构建云原生应用的动态服务发现、配置和服务管理平台,提供注册中心、配置中心和动态DNS...

Spring 中@Autowired,@Resource,@Inject 注解实现原理

使用案例前置条件:现在有一个Vehicle接口,它有两个实现类Bus和Car,现在还有一个类VehicleService需要注入一个Vehicle类型的Bean:publicinte...

一文带你搞懂Vue3 底层源码

作者:妹红大大转发链接:https://mp.weixin.qq.com/s/D_PRIMAD6i225Pn-a_lzPA前言vue3出来有一段时间了。今天正式开始记录一下梗vue3.0.0-be...

一线开发大牛带你深度解析探讨模板解释器,解释器的生成

解释器生成解释器的机器代码片段都是在TemplateInterpreterGenerator::generate_all()中生成的,下面将分小节详细展示该函数的具体细节,以及解释器某个组件的机器代码...

Nacos源码—9.Nacos升级gRPC分析五

大纲10.gRPC客户端初始化分析11.gRPC客户端的心跳机制(健康检查)12.gRPC服务端如何处理客户端的建立连接请求13.gRPC服务端如何映射各种请求与对应的Handler处理类14.gRP...

聊聊Spring AI的Tool Calling

序本文主要研究一下SpringAI的ToolCallingToolCallbackorg/springframework/ai/tool/ToolCallback.javapublicinter...

「云原生」Containerd ctr,crictl 和 nerdctl 命令介绍与实战操作

一、概述作为接替Docker运行时的Containerd在早在Kubernetes1.7时就能直接与Kubelet集成使用,只是大部分时候我们因熟悉Docker,在部署集群时采用了默认的dockers...

在MySQL登录时出现Access denied for user ~~ (using password: YES)

Windows~~~在MySQL登录时出现Accessdeniedforuser‘root‘@‘localhost‘(usingpassword:YES),并修改MySQL密码目录适用...

mysql 8.0多实例批量部署script

背景最近一个项目上,客户需要把阿里云的rdsformysql数据库同步至线下,用作数据的灾备,需要在线下的服务器上部署mysql8.0多实例,为了加快部署的速度,写了一个脚本。解决方案#!/bi...