历史文档小程序启动速度优化实践
Posted Sahadev_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了历史文档小程序启动速度优化实践相关的知识,希望对你有一定的参考价值。
这篇文章是2018年3月写的,本身只是做了简单的内部分享。近期被人问题这段经历,发现忘得一干二净,于是再拿出来回顾回顾。
前言:前端应用的启动速度一向是移动终端的优化重点,因为这是面向用户进入的大门。良好的启动速度无异于会带来良好的用户体验。
本篇文章主要介绍每日优鲜主商城小程序的启动速度优化方法。
启动时间消耗概览
小程序的启动时间主要分为以下几个阶段:
- 微信客户端比对版本差异,下载并加载代码。
- 小程序本身的初始设置,业务逻辑请求处理。
- 页面的渲染。
所以,小程序从点击启动到渲染完成主要会经历以上几个过程,接下来我们针对以上部分进行优化说明。
代码下载加载阶段
众所周知,小程序本身使用的是JS,html,CSS等语言进行开发。所以在代码发布时,微信会对这些文本文件进行必要的体积压缩。除此之外还有应用所需的图片资源文件。
所以发布后的小程序主要包括:
- 压缩后的JS,HTML,CSS等文本文件。
- 应用中所需的图片资源文件。
这些文件的总体积便会影响到小程序第一阶段的加载速度。而在这些文件中,图片资源文件占了总体积将近80%的比例。
所以,针对这一阶段的主要优化方式为:
-
将不必要的图片资源存储于服务器,通过url加载。 不必要的图片资源包括但不限于:营销活动的背景图、活动的规则说明图、活动Banner、GIF图等。在优化时,按照文件大小从大到小排序,分情况处理。
-
将必要的Icon图做压缩,如果不需要Aphla通道的图可转换为JPEG格式。
推荐在线图片压缩处理网站:https://tinypng.com/ -
对于按钮背景图等可使用CSS达到同样效果的使用CSS绘制。
-
避免冗余代码,及时移除废弃代码。
代码初始化,业务逻辑请求处理
这一部分主要与业务本身联系紧密,需要根据业务需要来进行优化处理。以下主要针对主商城的业务模式进行优化说明:
小程序优化之前的启动过程如下:
- 登录 -> 获取上次下单地址 -> 请求货架信息 -> 通过购物车信息 -> 渲染
第二次启动过程如下(与首次相同):
- 登录 -> 获取上次下单地址 -> 请求货架信息 -> 通过购物车信息 -> 渲染
小程序优化之后的首次启动过程如下:
- 登录 -> 获取上次下单地址 -> 请求货架信息 -> 分页渲染 -> 同步购物车信息
第二次启动过程如下(没有登录过程):
- 获取用户上次下单地址 -> 请求货架信息 -> 分页渲染 -> 同步购物车信息
可以看到,这里主要针对登录做了优化,并将页面渲染前置。
在优化过程中,发现小程序每次都会重新登录,显然不需要这么做。如果将登录状态存储在本地,可以减少登录一系列过程的开销。但是为了保证登录状态的过期问题,所以专门对网络框架层做了处理:如果后端返回statusCode为401或者403,或者statusCode为200但是内部的code为102,则会重新走登录过程。登录完毕之后会再次请求原有的接口,好处在于业务层并不需要关心也不会感知到token过期的问题。
渲染
在优化之前,小程序会显示一个Loading图,直到购物车信息同步完毕。我们为了尽快的将信息展示给用户,将这个Loading图前置到了货架信息开始渲染时,也就是说,在渲染货架信息的时候,便不再显示Loading。这个过程很重要,对启动速度影响很大。
除此之外,在初次渲染时只渲染少量的数据,但足满一屏。通过测试发现,渲染全部数据与渲染一屏的数据时间差异较大,我们在用户需要查看更多数据的时候,再对剩下的数据同样进行分页渲染:货架数据一次10条。
页面渲染的同时,我们也在同步购物车信息,做到了并行进行。在同步完成之后,再将购物车的信息更新到货架上。
总结
经过以上大幅优化手段,小程序启动速度明显加快。在开发者工具上的运行结果为:之前首次是4秒,优化之后首次是2秒。第二次进入之前还是4秒,优化之后为1.5秒。可以算是”秒开“了。
这里我们并没有涉及网络优化方面,但这并不意味着网络部分不需要优化。如果在实际开发中,网络部分不再合理的范围内,则需要考虑服务器相关的优化:代码优化、DNS优化、服务器地理位置优化、网络环境优化、网络包压缩以及适时不采用HTTPS等加密传输等方向。另外由于小程序是运行在微信内置的相关引擎上,所以在我们不可控的范围内也有一定的开销,这一部分需要及时关注微信方面的更新。
工具
优化应用需要一个得力的工具,这里为大家共享一个执行时间统计工具,这款工具可以统计两个点之间所花费的时间,使用方便简单。以下是JS语言,其它语言可参考实现方式:
let index = 0;
function logTime(arg) {
index++;
const app = getApp();
let current_date = new Date();
let offsetTime = 0;
if (app && app.globalData.lastTimeLogFunctionCallTime !== 0) {
if (app.globalData.startTotalTime == 0) {
app.globalData.startTotalTime = current_date.getTime();
}
offsetTime = current_date.getTime() - app.globalData.lastTimeLogFunctionCallTime;
}
let desc = current_date.getMinutes() + "分" + current_date.getSeconds() + '秒' + current_date.getMilliseconds() + "毫秒";
if (app && app.globalData.startTotalTime != 0) {
let totalStartTime = new Date(current_date.getTime() - app.globalData.startTotalTime);
desc += ", 启动总耗时: " + totalStartTime.getMinutes() + "分" + totalStartTime.getSeconds() + "秒" + totalStartTime.getMilliseconds() + "毫秒";
}
if (offsetTime != 0) {
let time = new Date(offsetTime);
desc += ", 与上一次调用的差值为: " + time.getSeconds() + "秒" + time.getMilliseconds() + "毫秒";
if (DEBUG_STACK_MODE) {
let currentCallStack = (new Error).stack;
desc += ", 当前的调用栈为: " + currentCallStack;
}
}
logi('TIME_TAG ==> ' + index + (arg ? " " + arg : "") + ' 当前方法的调用时间为: ' + desc);
if (app) {
app.globalData.lastTimeLogFunctionCallTime = current_date.getTime();
}
}
function logi(infoMsg) {
if (DEBUG_MODE) {
console.info(infoMsg);
}
}
文章本身就到此结束了,但结尾有些潦草,对感兴趣的同学借鉴意义也不大。因为大幅节省时间的点还是在于业务本身。不过上面的工具帮助我定位了哪一段代码之间具体的执行耗时时间,还是比较有用的。
以上是关于历史文档小程序启动速度优化实践的主要内容,如果未能解决你的问题,请参考以下文章