小程序首次启动性能优化:下载、加载与初始化流程详解

2024-07-22
来源:网络整理

1. 首次启动性能优化 1. 用户首次打开小程序时,一般会观察到如下图所示的三种状态

这张图里的三个状态分别对应什么呢?当一个小程序启动的时候,微信会展示这个小程序的固定启动界面,这个界面包括小程序的图标、名称、加载提示图标。

此时微信会在后台完成几个工作:下载小程序代码包、加载小程序代码包、初始化小程序首页。下载的小程序代码包并不是小程序的源代码,而是编译、压缩、打包后的代码包。

2. 小程序加载顺序

在小程序启动前,微信会为小程序准备一个通用的运行环境,这个运行环境包括若干个线程供小程序使用,初始化小程序基础库,预执行通用逻辑,尽可能做好小程序启动的准备,这样可以大大减少小程序的启动时间。

通过这张图,我们可以对比发现,第一张图是小程序首次启动时,资源准备(代码包下载);第二张图是业务代码的注入,登陆页的第一次渲染;第三张图是请求登陆页数据时的状态(部分小程序存在)。

3.优化方案

控制包大小:代码上传前进行压缩,除小图标外的静态图片资源放入CDN,去除无用代码;

包加载:根据业务场景,把用户访问率高的页面放在主包中,访问率低的页面放在子包中,按需加载;

分包预加载:在进入小程序页面时,框架会自动预下载可能需要的子包,以提高进入后续分包页面时的启动速度。对于独立分包,主包也可以预下载。分包预下载官方文档链接

独立子包技术:不同于子包,与主包无关,在功能相对独立的子包中,用户只需下载子包资源即可;独立子包官方文档链接

二、渲染性能优化 1、数据渲染优化

在双线程界面渲染中,小程序的逻辑层和渲染层是两个独立的线程。在渲染层,宿主环境会将 WXML 转换成对应的 JS 对象。当逻辑层数据发生变化时,我们需要利用宿主环境提供的方法将数据从逻辑层传递到渲染层,然后对比前后的差异,将差异应用到原始 Dom 树上,渲染出正确的 UI 界面。

页面初始化的时间大致由两部分组成:页面初始数据通信时间和初始渲染时间。数据通信时间是指从逻辑层开始组织数据到视图层完成接收的时间。当数据量小于64KB时,总时间可以控制在30ms以内。传输时间一般与数据量呈正相关,传输过多数据会明显增加这个时间。因此,减少传输数据量是减少数据传输时间的有效方法。

在传输数据的时候,逻辑层会执行 JSON. 来去除数据中不可传输的部分,然后将数据发送给视图层。同时逻辑层还会将设置的数据字段与数据进行合并,这样开发者就可以使用 this.data 来读取变化的数据。因此,为了提高数据更新的性能,可以参考以下方法:

2. 长列表优化解决方案

无限下拉加载会因为显示大量数据而导致性能问题。很多 C 端常用的做法是“只渲染需要的元素”。虚拟列表是按需显示思想的一种实现,也就是说虚拟列表是一种根据滚动容器元素的可见区域,渲染长列表中一部分数据的技术。简单来说,虚拟列表就是指“可见区域渲染”的列表。有三个概念需要理解:

滚动容器元素:一般来说,滚动容器元素都是对象。但是,我们可以通过布局在页面中指定一个或多个滚动容器元素。只要一个元素内部可以产生水平或垂直滚动​​,那么这个元素就是滚动容器元素。考虑到每个列表项只是渲染一些纯文本。本文仅讨论元素的垂直滚动。

可滚动区域:滚动容器元素内部的内容区域。假设有100个数据项,每个列表项的高度为50,则可滚动区域的高度为100*50。一般可以通过(滚动容器)元素的属性获取可滚动区域当前的具体高度值。用户可以通过滚动来改变列表在可见区域中的显示部分。

可见区域:滚动容器元素的视觉可见区域。若容器元素为对象,则可见区域为浏览器的视口大小(即视觉视口);若容器元素为div元素,其高度为300,且右侧有垂直滚动条可供滚动,则视觉可见区域即为可见区域。

实现虚拟列表,就是在用户滚动的时候改变列表在可见区域中渲染的部分。具体步骤如下:

计算当前可见区域的起始数据

计算当前可见区域的结束数据

计算当前可见区域的数据并渲染到页面

计算对应数据在整个列表中的偏移位置,并设置到列表中

计算对应数据相对于可滚动区域底部的偏移位置,并设置到列表中

虚拟列表的实现原理可以参考这篇文章:虚拟列表实现原理简介

3. 长列表的部分渲染技术

一个列表中,有 n 条数据,采用上拉加载更多的方式,如果此时想点赞其中某一条数据,并且能够及时看到点赞的效果,可以使用全局刷新,点赞完成后,重新获取数据,全局重新渲染。这样做的好处是:方便快捷!缺点是:用户体验极差,当用户刷新超过 100 条数据时,重新渲染量会很大,并且会出现空白期(没有渲染)。

优化步骤:

3. 生命周期优化4. 图片静态资源预加载

在日常小程序开发中,有很多大图片放在 CDN 上,需要显示时,如果不进行预加载,图片可能无法及时显示,导致体验不佳。因此,下面这种方式实现图片预加载功能,可以封装成组件。

思路就是将图片添加到页面中,然后设置不可见,然后加载图片,实现预加载的功能。

1.添加模板文件:img-.wxml

微信开发程序技术用到小程序吗_开发微信小程序用什么技术_开发微信小程序用到的技术

2.添加js文件:img-.js

/**

{

/**

this.page.data.imgLoadList = [] //下载队列 this.page._imgOnLoad = this._imgOnLoad.bind(this) this.page._imgOnLoadError = this._imgOnLoadError.bind(this)

/**

let list = this.page.data.imgLoadList, imgInfo = this.imgInfo[src] if (callback) this.callbacks[src] = callback //已经加载成功过的,直接回调 if (imgInfo) { this._runCallback(null, { src: src, width: imgInfo.width, height: imgInfo.height }) //新的未在下载队列中的 } else if (list.indexOf(src) == -1) { list.push(src) this.page.setData({ 'imgLoadList': list }) }

(埃夫){

让 src = ev...src,

= 也..,

= 也..

//记录已下载图片的尺寸信息 this.imgInfo[src] = { width, height } this._removeFromLoadList(src) this._runCallback(null, { src, width, height })

(埃夫){

让 src = ev...src

这个。(源文件)

this.(' ', { src })

//从下载队列中删除图像

(来源){

让列表 = this.page.data。

列表。(列表。(src),1)

本页。({'':列表})

//执行回调

(错误,数据){

让 = 这个。[数据.src] || 这个。

(错误,数据)

这个。[数据.src]

. =

3、在需要使用预加载功能的xxx.wxml页面中添加模板文件及使用代码:

4.引入该文件,并在需要使用预加载功能的页面的xxx.js文件中使用代码:

来自'…/…//img-.js';

让 = [

'',

'',

“”

// 初始化图片预加载组件,指定统一的加载完成回调

这。=新的(这,这..绑定(这));

.(项目 => {

这..加载(项目)

})

分享