当前位置:SEO自学网 > 自媒体运营与推广 > 秒开之路——百度百科小程序性能优化实践

秒开之路——百度百科小程序性能优化实践

admin2022年05月21日 19:10:45自媒体运营与推广24

导语:作为头部小程序,百度百科的用户体验对于百度智能小程序生态的用户体验有重要的作用。页面加载速度是影响用户搜索体验的一个重要因素。百度APP对用户行为的研究表明,页面首屏的加载时间在1秒以内的站点或小程序,用户的留存率会越高,更符合用户对快捷搜索体验的期待。本文是智能小程序直播课的文字版本,将为大家详细讲解百度百科小程序(以下简称“百科”)在达到“秒开”方面做了哪些方面的优化,视频版本请看直播回放:https://live.baidu.com/m/media/pclive/pchome/live.html?room_id=4959977629&source=h5pre。

一、百科小程序概况

百科小程序主要的页面有词条页,首页,秒懂视频feed页面,个人中心以及相关二级页。

默认图片

图1:百科明星loft特型词条

百科小程序编译后代码总大小1119.8k,其中主包大小856k,代码总行数20.3w行,页面总数有59个,其中8个页面在主包内。在这些页面中,词条页流量占居首位,高达87.7%,其他主要页面,秒懂视频页占比4.7%,图片页占比3.5%,首页占比0.2%,剩余的其他页面一共占比3.9%,从流量占比我们可以看出,词条页是百科小程序的主要流量页面,所以百科小程序的性能优化,词条页就成为了重点优化页面。

百科小程序采用的是Okam小程序框架,在Okam框架和小程序原生组件的基础上,通过VUE及VUE组件实现的页面功能,包括公共组件和私有组件,然后后端数据是通过异步API请求到前端的。Okam代码再通过编译器生成小程序原生代码,最终展现给用户。Okam框架的的优势主要提现在开发效率和维护上,Okam把小程序原生的目录结构js,json,css,dom等文件合成了一个VUE文件,这样的话,在开发阶段是比较便捷的,开发效率快,代码也比较容易维护。另外,Okam可以编译成多个小程序,这样一套代码就可以实现多个平台的小程序,节约成本,大家如果对Okam感兴趣可以看一下官方文档详细了解一下。

默认图片

图2:百科小程序架构示意图

二、性能优化详解

在介绍优化手段之前,我们一起来看一下小程序的启动流程,用户点击打开小程序后,进行小程序包的下载,下载后逻辑层和渲染层首先并行执行,然后在initData处改为串联执行,大概的过程,逻辑层依次执行加载动态库和插件、加载逻辑代码、执行onLaunch,与此同时,渲染层依次执行加载模板和样式文件(包括app.css,page.css和page.swan等相关文件)、然后加载SJS(SJS是智能小程序的一套自定义脚本语言)、加载当前页面所有使用到的自定义组件(包括动态库和插件)。渲染层完成以上执行后,会用逻辑层收集到的initData进行首次内容绘制(也就是FCP),其中initData主要包含了小程序App、页面和自定义组件的初始数据。首次内容绘制完成后,渲染层向逻辑层发送firstRendered事件,逻辑层开始执行生命周期onLoad等,完成以上所有流程后,会触发首次有意义的渲染,也就是FMP。

默认图片

图4:百度小程序启动流程

接下来,我们一起来看一下百科小程序性能优化的主要优化手段,这些优化手段分成了4大类:

第一类,包体积优化;

第二类请求优化,其中包含以下5点。

1. 改造request,之所以要改造是分析发现之前百科的request的实现多处对小程序原生异步接口的处理都用Promise包了一层,一共有4个地方,这样其实使用上方便了,但是实际上增加了处理耗时,针对这个问题,百科进行了request脚本的重写,把4个promise优化成了1个,这里也提醒一下大家在首屏渲染前尽量少用Promise。

2. 是关于小程序入口结果卡的,主要是结果卡前置prelink时机,这里开发者们不需要关注太多,只需要在app.js配置一下prelink的地址即可(https://baikeapi.baidu.com/smartapp/prelink?app=baike),这个操作能让小程序尽早的对业务请求建立链接。

3. 动态库支持preload,百科目前主要用到了评论组件动态库。

4. 请求提前。

5. 是后端接口的优化,主要包括精简词条页首屏接口数据和星图接口耗时的优化

第三类,渲染优化;

第四类,编译优化,主要包括两点,一是全量优化包,其中包含app.js优化和自定义组件拆分优化等。二是接入css module。编译优化的这两点开发者几乎没有什么代码上的工作量,只需要申请开启白名单,然后进行小程序效果回归,最后灰度上线观察没问题后全量即可。

接下来会对以上优化手段中的包体积优化、请求提前、渲染优化进行详细介绍。这三点也是对于百科小程序来说优化收益比较明显的。

2.1 包体积优化

结合前面介绍的小程序启动流程,小程序包的下载与解析是整个启动过程中的一个重要阶段,这个阶段的耗时与小程序包大小呈正相关,将直接影响到逻辑层initData 完成收集的时间,从而影响到首屏渲染。因此,包体积的优化能减小 initData 的准备时间,提前首屏渲染的起始点,进而减小首屏渲染时长,也就是FMP。

在包体积优化上,百科主要做了以下三件事。

1. 主包大小减到极致,减到最小,进行合理分包。

整体来看,百科小程序的包大概分为主包和分包,分包主要有三个,分别是subPage,,general,editor。主包有8个页面,主要有词条页,秒懂视频页,首页,图片页,无网络提示页。划分依据:按pv分,靠前的页面,或者有对外合作而不能轻易更改路径的页面。subPage包主要有36个页面,主要有图册页,演员表页,星图页,AR页,参考资料页,百科贡献者页,音乐专辑页以及参演电影页等,划分依据:pv少,功能独立单一,一般是词条页等页面的二级页。general包主要有14个页面,主要有搜索页,个人中心页,社区帖子页等,划分依据:一些常用的页面,页面入口一般存在于topbar、bottombar等公共组件里,即多个页面都有入口的放在本包内。最后一个editor包,目前只有一个页面——概述图册编辑页,划分依据:编辑提交类页面,编辑器等,比如后面小程序要实现文本编辑器就放入此包内。

默认图片

图5:百科小程序分包情况

1. 包内不要放过多或者过大的文件资源。之前百科图片资源是都放在了包内存储和维护,随着业务功能的不断迭代和新增,图片等资源会越来越多,包体积将会越来越大,那么包下载就会越来越耗时,最后导致FMP越来越退化。所以这里建议不要把图片等资源放到包内存储。在这点上,百科是把图片资源从包内迁移到了百度云CDN上面来存储和管理,给主包瘦了个身。

2. 最后一点,也是跟工程意识和代码规范相关的,要及时清理垃圾,保持项目的干净,下线的功能和逻辑要删除,千万不要注释代码。历史经验表明,注释的代码一般是不会再次上线,注释的代码给后面的维护也会带来困难,后面的人也不会轻易删,这样垃圾就一直在。所以再次强调,不要注释代码,养成良好的编码习惯。

2.2 请求提前

从小程序生命周期原理图中可以看到,小程序生命周期依次是app.onLaunch->app.onShow->page.onInit->page.onLoad->page.onShow->page.onReady->page.onHide-> unload-> end

默认图片

图6:小程序生命周期原理图

百科小程序在请求时机上,最开始是在page的onLoad里面进行数据请求,然后提前到了page的onInit里面,再然后提前到了app的onLaunch中,直到现在提前到了app的onPrefetch。从图中我们也明显能看到数据请求从page级的生命周期提前到了app级的生命周期的初始时机,一个飞跃式的提前。这里重点说一下app的onPrefetch。在刚刚介绍小程序生命周期中没有提到app的onPrefetch,onPrefetch是小程序基于百度结果卡实现的一个预取能力。这个预期能力的时机是可以配置的,主要有点击结果卡和展现结果卡。对于百科结果卡这种高pv的卡显然是不适合在展现的时候进行预取,所以百科自然设置的是点击时预取。

默认图片

图7:百科小程序请求时机的历史演变

首先我们需要建一个prefetch.js预请求文件,在这个文件里面主要通过onPrefetch来监听预取事件,然后执行业务的数据逻辑。如图8所示,在onPrefetch的事件监听里面有个lemmaRequest方法,这个就是百科词条页的数据请求方法。

默认图片

图8:prefetch.js文件

在建立预请求文件之后,还需要在app的入口文件里面配置预取相关的配置,如图9,主要是开关的配置、预取文件路径的配置以及预取时机的配置,预期时机默认为点击时预取,满足百科点击预取的诉求,所以百科这里用了默认值没有配置,如果大家有展现预取的诉求,可以增加一个state的配置项,设置成show即可。

默认图片

图9:开关、预取文件路径以及预取时机的配置

在实现的过程中,也遇到了一些问题——比如,如何解决发起两次请求问题,就是说在首次调起小程序时app的onPrefetch里面已经发起了请求,page的onInit里面应该不需要再次发起请求,直接执行逻辑和渲染即可。对于这个问题,百科是通过缓存请求来解决的。具体实现是,先建立一个词条页缓存区,通过请求参数生成的字符串作为每次请求的key值,request来作为value值。当调用请求方法时先根据这个key值查询缓存区是否已经存在此请求,如果存在等待数据返回后执行逻辑和渲染,如果缓存区没有当前请求则发起请求。缓存的清理一般是在onInit的数据请求回调中和请求异常时。

默认图片

图10:请求缓存的实现

2.3渲染优化

词条页的渲染优化,主要包含三部分:首屏分析与划分、渲染优化和逻辑优化。

首先,给大家介绍一下词条页的首屏分析,在百度小程序里面,百科应该属于功能和逻辑相对比较复杂的小程序之一,单看词条页,种类和情况就太多了,上面三个图的情况只是冰山一角,图11中的三张截图也是挑选的相对通用的三种情况。接下来,给大家介绍一下这三个图上面包含的功能组件,左边是明星特型loft词条,首屏主要包含topbar,loft,权威编辑模块,card,右侧悬浮区;中间是普通词条,首屏主要包含了topbar,topImage,card,底bar,右侧悬浮区;右边是含有星图结构关系的词条,首屏主要包含topbar,顶部星图模块,topImage,lemmaInfo, extraInfo,权威编辑模块,card,底bar和右侧悬浮区。

默认图片

图11:百科词条首屏分析示例

根据举例的首屏分析,我们对模块进行梳理,总结出覆盖几乎所有词条情况的首屏模块。图12就是对词条页模块组件的梳理以及总结出的首屏模块,此处不做一一介绍。

默认图片

图12:首屏模块梳理

1. 分段渲染

在首屏分析和模块梳理的基础上,实现了分段渲染。我们把词条页的渲染分为了四个阶段,第一阶段首屏渲染,第二阶段正文前内容渲染,第三阶段正文内容渲染,第四阶段正文后内容渲染,首屏渲染又分了两个阶段的渲染,正文渲染主要还实现了分屏渲染。分段渲染的关键实现是在setData回调中通过改变控制渲染开关的值。

默认图片

图13:分段渲染示意图

接下来,来看一下主要代码片段。分别是beforeContentRender(正文前内容渲染开关)和beforeContentRendered(正文内容渲染开关) 。

默认图片

和contentRenderDone(正文后内容渲染开关):

默认图片

然后开关通过vue的if来实现对dom渲染的控制:

默认图片

默认图片

首屏区域的实际划分:

默认图片

2. 分屏渲染

百科词条页可以分成两大类,普通词条和loft特型词条。普通词条在接受到数据后先进行第一阶段的数据处理,然后通过setData进行第一次渲染,即首屏;然后再执行第二阶段的数据处理,再执行正文前内容的渲染。Loft特型词条在接受到数据返回后进行第一阶段的数据处理然后通过setData进行第一次渲染,再进行第二阶段的数据处理(主要是loft数据的处理),通过setData进行第二次渲染,即首屏;然后再执行第三阶段的数据处理,再执行正文前内容的渲染。对比看两者的主要区别在于特型词条首屏多了一次逻辑处理和渲染,主要是loft梳理的从处理和渲染。同样首屏的分段还是通过setdata回调和渲染开关来控制的。

分屏渲染主要靠pageScroll和分页元素来实现,在页面滚动里面监听分页元素的高度,即判断到达页底,在合适的时机setData正文数据,进而实现分屏渲染。

默认图片

默认图片

默认图片

经过这一系列的优化,百科小程序的Q3 FMP数据从最高点的1504ms降到最低点982ms,大概优化了522ms,Q3季末在9月22号首次秒开,也是百科小程序历史性的一刻,在过去,19年、20年百科小程序的FMP一度高达1800ms,当时觉得秒开对于百科小程序来说是一件遥远而且不可能完成的事情,但是今天我们做到了。在这个优化的过程中,我们坚信“世上无难事,只怕有心人”,发挥极客精神,追求极致体验,将一直作为百科小程序的目标。

大家有任何问题,可以在评论区与我们交流,我们会集中邀请作者解答。

来源:百度搜索资源平台 百度搜索学堂


扫描二维码推送至手机访问。

版权声明:本文由SEO自学网发布,如需转载请注明出处。

本文链接:http://www.seozixuewang.com/post/5171.html

“秒开之路——百度百科小程序性能优化实践” 的相关文章