【JavaScript】微信小程序:高效性能优化策略与实践
本文作者:黄启聪,碧桂园服务前端开发高级工程师,专注于运用前沿的Web技术提升工作效率,并致力于打造卓越的交互式用户体验。
01 前言
目前,凤凰会商城支持全国商城、门店、酒司令、地推、群接龙等多种业务,并且具备多端能力。一套代码可以在凤凰会APP、移动端H5和微信小程序中运行,研发效率得到提高的同时,还能够更快地支持业务迭代。
随着业务的持续更新和迭代,凤凰会商城小程序的渲染性能逐步下降,微信后台性能评估表现一般,同时在互联网人口红利消失、增量变缓的背景下,用户对性能的要求不断提高。因此,性能优化已成为开发者必须关注并解决的重要课题。本文将介绍微信小程序性能优化的关键策略和实践,帮助开发者提供更出色的用户体验,以便更好地留住来之不易的增量用户,进一步助力业务成长。
02 性能指标概述
在介绍性能优化之前,我们先来了解一下小程序的启动流程。了解小程序的启动流程可以帮助开发者更有针对性地选择性能优化的手段,分析性能优化的效果,并概述常见的性能指标和问题,为后续的优化工作打下基础。
其中关键的几个监控指标字段和对应意义如下:
上表对应凤凰会商城页面加载的几个关键阶段,下面就门店示例其他页面类推即可:
微信小程序评测中,性能评测报告会根据上面指标加权平均得出性能评定,如图:
性能优化是通过各种技术手段和策略来提高小程序的代码包体积、代码注入、首屏渲染性能和网络请求等方面的表现,从而提升应用运行性能和用户体验需求。
03 性能优化策略和实践
1、优化启动时间
(1)分析包体积构成,移除冗余无用的模块
启动时间是用户对小程序的第一印象,直接影响用户的留存和使用率。因此,我们深入分析了启动时间对用户体验的影响。
从小程序启动流程中可以看出,下载时间是启动时间中的重要瓶颈。当用户首次访问小程序或小程序版本更新时,代码包的下载会影响启动时间。
下载时间长短受到网络环境、代码包压缩后大小以及是否命中增量更新等因素的影响。为了优化用户体验,小程序平台将单个小程序代码包的大小上限限制为2M。针对代码包体积的优化,我们采取了以下策略:
(2)分包策略优化
根据分析工具的结果显示,商城小程序的优化重点是从主包中去除多余的类库依赖,并将非主包依赖的配置文件下沉到对应的业务子包中。通过这样的优化措施,可以减少代码冗余并对代码进行精简,从而提高小程序的性能和效果。
分包策略优化,每个子包体积控制在1.5M以下,理想状态控制在500K左右。
将用户常用页面汇集到一个相对独立的子包中形成闭环访问,从而避免页面切换时需要重新下载相关联的其他子包内容。如下图所示:
微信开发者工具的代码包体积分析显示,经过调整后每个关键业务子包的大小控制在500K左右。这意味着用户将能够更快地加载关键页面,从而提升用户体验。
(3)分包预下载
通过路径分析来制定分包预下载策略,可以将小程序的页面根据依赖关系进行划分,将相互依赖的页面进行预下载,可以有效减少页面切换时的加载时间。页面依赖关系可以通过微信开发者工具的“数据分析”功能中的“行为分析”模块查看。页面路径分析如图所示:
如果用户访问小程序的主页或商品列表页面后,下级路径中访问搜索页的比例较高,则可以配置在访问到搜索页的上级页面时就预下载搜索页。代码示例如下:
点击查看代码
{
"preloadRule": {
"pages/index/index": {
"network": "all",
"packages": [
"search",
"oto",
]
},
"pages/goodsDetail/goodsDetail": {
"packages": [
"search",
"pagesLogin",
"oto"
]
},
"pages/user/user": {
"packages": [
"pagesLogin"
]
},
"pagesLogin/login/login": {
"packages": [
"privacy"
]
}
}
}
优化启动时间的实践技巧包括减少代码冗余、调整分包策略和页面预加载。通过精简代码、合理加载资源和提前预加载页面,可以显著缩短小程序的启动时间,提升用户体验。
2、优化代码注入
代码注入是小程序启动过程中的性能瓶颈之一。我们将分析代码注入对性能的影响,并介绍一些减少注入代码数量和优化注入效率的方法,如按需注入、异步注入和使用合适的代码格式等,以提升小程序的代码注入性能。针对代码注入优化主要采取的策略是:
(1)启动过程中减少同步API的调用
在小程序启动流程中,会顺序同步执行App.onLaunch、App.onShow、Page.onLoad和Page.onShow。
在小程序初始化代码和上述启动相关的生命周期中,应尽量减少或不调用同步API。
同步API虽然使用起来更简单,但会阻塞当前JS线程,影响代码执行。因此,如非必要,应尽可能使用异步API代替同步API,并将启动过程中非必要的同步API调用延迟到启动完成后进行。
针对减少同步API的调整策略:
同步API首次调用成功后,将结果缓存起来,之后再次调用时直接从缓存中获取。
同步API一般都有对应的异步接口,可以尽量使用异步接口。
同步API可能会影响页面渲染,可以考虑延迟到渲染完成后再调用。
(2)按需注入
通常情况下,小程序启动时会将所有代码包中的JS代码全部注入,包括未访问的页面和未用到的自定义组件,这会影响注入耗时和内存占用。
点击查看代码
{
"lazyCodeLoading": "requiredComponents"
}
注意:启用按需注入后,页面中的所有自定义组件都会被注入和加载,建议开发者及时移除未使用的自定义组件声明,并尽量避免在全局声明使用率低的自定义组件,否则可能会影响按需注入的效果。
通过合理地管理和优化代码注入,可以减少不必要的代码注入数量,提高注入效率,从而提高小程序的启动速度和运行性能。
3、优化渲染性能
渲染性能直接关系到小程序的流畅度和响应速度。在本节中,我们将探讨减少页面渲染时间的关键策略,包括减少DOM元素、避免过度绘制和使用CSS动画等,帮助开发者提升小程序的渲染性能。
(1)避免引用未使用的自定义组件
通过减少不必要的组件加载和渲染,可以显著提升小程序的启动速度和渲染性能。为了避免引用未使用的自定义组件,我们可以采取以下实践策略:
分析和评估组件的使用情况:在开发过程中,仔细分析并评估每个自定义组件的使用情况。确保只在需要的页面或组件中引用和使用自定义组件,避免不必要的引用。
移除未使用的组件引用:定期审查代码并检查自定义组件的引用,移除未被使用的组件引用。可以通过代码静态分析工具或IDE的功能来辅助识别未使用的组件引用。
动态引用组件:对于一些特定场景,可以考虑在需要的时候动态引用自定义组件。通过使用条件判断或动态渲染的方式,根据实际需要来决定是否引用该组件,避免在不需要的情况下加载和渲染组件。
(2)非必须组件延迟渲染
通过非必须组件延迟渲染可以将未使用到的组件的渲染过程延迟到用户需要使用时才进行,可以减少首次渲染DOM元素渲染数量,从而提升首屏渲染速度。代码示例如下:
点击查看代码
// common/mixins/universal.js
export default {
data() {
return {
isLazyShow: false,
}
},
onReady() {
this.isLazyShow = true
},
}
// main.js
import universal from "@common/mixins/universal"
Vue.mixin(universal)
// 门店页面 oto.vue
<template>
<Page>
....
<!-- 提升页面初始化速度 -->
<view v-if="isLazyShow">
<!-- 多规弹窗 -->
<goods-sku />
<!-- 分享海报 -->
<fhh-poster-popup />
<!-- 省钱卡秒杀商品弹窗 -->
<common-dialog />
定位切换门店
<uni-popup />
...
</view>
</Page>
</template>
通过优化页面结构、减少不必要的DOM元素和延迟渲染等方法,可以有效降低小程序的页面渲染时间,提升用户的交互体验。
** 4、优化网络请求**
网络请求是小程序中常见的性能瓶颈之一。我们将分析网络请求对性能的影响,并介绍一些减少请求次数和优化请求大小的方法,如合并请求、缓存数据和使用合适的数据格式等,以提升小程序的网络请求性能。
(1)缓存请求数据
小程序提供了wx.setStorage、wx.getStorage等读写本地缓存的能力,数据存储在本地,返回会比网络请求快。当使用小程序的本地缓存功能时,可以优先从缓存中获取数据来渲染视图,然后在后台进行网络请求并更新缓存。以下是一个示例代码,演示了如何使用本地缓存读取和更新数据:
点击查看代码
// 从缓存中获取数据
function getDataFromCache() {
try {
const value = uni.getStorageSync('myData'); // 使用指定的键名获取缓存数据
if (value) {
// 如果缓存中存在数据,则使用缓存数据进行渲染
renderView(value);
} else {
// 如果缓存中不存在数据,则进行网络请求
fetchDataFromServer();
}
} catch (e) {
// 异常处理
console.error('Failed to read data from cache:', e);
fetchDataFromServer();
}
}
(2)合并请求接口
当在小程序中需要同时发起多个接口请求,并在所有请求完成后进行处理时,可以使用Promise.all方法来合并策略。Promise.all接受一个由Promise对象组成的数组,并返回一个新的Promise对象,该Promise对象在所有的Promise都成功解析后才会被解析。
以下是一个示例代码,展示了如何使用Promise.all合并多个接口请求的策略:
点击查看代码
// 多个接口请求合并策略
function mergeApiRequests() {
const promiseValues = [
apiGoods.getGoodsStaticInfo(o),
apiGoods.getGoodsStaticOtherInfo(o),
apiGoods.getGoodsStaticDrpInfo(o),
apiGoods.getGoodsStaticUserInfo(o),
]
Promise.all(promiseValues).then((responses) => {
const [goodsInfoRes,
otherInfoRes = {},
drpInfoRes = {}, userInfoRes = {}] = responses
// 所有请求都成功完成后的处理逻辑
console.log('All requests completed:', responses);
// 在这里对请求结果进行处理
// results 是一个数组,包含了每个请求的返回结果
})
.catch(error => {
// 请求过程中出现错误的处理逻辑
console.error('Error occurred during requests:', error);
});
}
// 调用合并接口请求函数
mergeApiRequests();
图片
上下、左右滑动查看更多
图片
通过合理地管理和优化网络请求,可以减少不必要的请求次数,从而提高小程序的加载速度和响应性能。
04 总结与展望
通过实施上述多种优化措施后,我们能够通过微信官方We分析平台轻松查看凤凰会商城小程序的性能指标和启动流程,从而及时发现并解决页面性能问题。这些优化措施显著提升了凤凰会商城小程序的运行性能——根据微信官方We分析平台的数据,凤凰会商城小程序性能表现上明显优于同类应用的均值360m。
通过实施上述优化措施,凤凰会商城小程序在性能方面取得了显著成果,这为我们提供了良好的基础,有助于持续改进和发展凤凰会商城小程序,为用户提供更出色的体验。
未来,我们将持续关注凤凰会商城小程序的性能优化,以确保用户能够快速、流畅地访问和浏览凤凰会商城,为用户带来便捷、高效和愉悦的购物体验。