Hybrid App性能优化之路

Hybrid App性能优化之路

主要从两个方面讲一下首屏数据展示耗时优化局部滚动长行列表优化

首屏数据展示耗时优化

1.首屏渲染的一般时序可以用如下的几个步骤:

首先点击打开页面,创建webview,进行页面的加载,页面加载完后,发送cdn请求去拉一些js和css的数据。

首先看一下首屏数据渲染,时候不用cgi?

首先想到的一点就是利用缓存。让cgi第一次拉取的数据是直接从缓存里读取出来的,等到加载完后再用实际的数据进行二次渲染;

但是这样会有两个问题:问题1–资源加载与cgi请求串行,就是我们必须等待资源加载完成后,才能发起这个cgi请求;问题2–数据存在二次渲染,因为当新的cgi数据拉取回来了,要重新刷一遍;

所以我们存在这样的一个思考?

1.能否让cgi请求与资源请求并行?

2.能否在第一次渲染时就渲染最新的数据?

我们可以思考进一步的优化方案:cgi预拉取方案

在head里面写一个jsonp发送cgi请求,这样就达到了与资源并行的目的;将拉取的数据存在一个对象中,判断数据是否返回,如果返回的话,就用新的数据进行渲染,如果没有返回那么还是用上面的缓存数据;

然而,在很多情况下,很多数据并不适合利用缓存的,比如一些页面打开的很频繁(一些热门的帖子,经常打开),或者只看一次就不看了;而且localstorage本身也有大小限制;

那么我们还有别的优化方法吗?

数据共享(工厂数据),提前渲染

比如下面的,两边很多数据都是一样的,比如标题以及其他的一些详细信息

把一些公用的数据单独提出出来,放在缓存中可以共享,提前渲染;

上面是数据的共享,有时候一些图片数据也是可以共享的

如何在右边大图还没有请求之前,利用左边已经缓存的小图片;右边可以先使用小图的拉伸大图,先看到模糊的大图,在看到清晰的大图;

进行下一步,资源加载

现在都是组件化的开发页面,但是组件开发在首屏加载中也会有一些问题

组件之间的逻辑耦合,是的加载一些非首屏的组件资源,这样倒是首屏的js体积过大;

给出的方案是 分离组件,区分环境后加载

最后是打开页面到穿件webview的优化

在点击页面到打开webview之间一般存在一定的延时,尤其是android的机型,一般有1-2秒的打开时间,这是时候,可以利用这段时间来尽量做一些事情。

通过观察者模式,去订阅和触发事件,从而在这段时间内,去拉取首屏的一些数据;

总结上面的几点

局部滚动长列表优化

一般的滚动长列表可以分为两种:一种是数目条数限定的,就几十条数据的滚动,另一种是无限滚动;

最初的实现方案是IScroll来解决;首先是数据有限情况下时,IScroll还是可以的,在松手的时候稍微有点卡顿,但是在几千条数据是,IScroll就卡的不行了。基本滚不动。也可以通过测试工具来测试两个页面的FPS,用IScroll来做,数目有限是上下波动比较大,但是能用;数目上千后,FPS上下波动特别大,随着列表数目的增加,卡顿现象越来越明显;

IScorll卡顿的原因是什么呢?

优化方案一:不用IScroll,替换成div的局部滚动;

但是,在条目比较多时,如果滚动过快,也会出现一些闪白的问题,所以对于列表项较多的列表,不推荐直接使用div局部滚动的方式;

思考??能否在利用div滚动特性的同时,规避滚动内容的闪白问题

优化方案二:利用div原生滚动内容层

所以采用一个折中的方案,内容层和滚动层分离,只需设置内容层的overflow:auto;

这样基本能解决问题,但是在小米2等低版本的android手机上,会发现滚动不是平滑的滚动,而是跳跃式的滚动,也就是说,很快滚动到后面,中间的条目很快就滚过去了,这是因为scroll不是实时触发的,而是结束后在进行样式变更。

那我们应该怎么办呢?

优化方案三:动态的增删dom

思考??我们是否可以不去滚动如此巨大的dom节点;在可视范围内的dom,增加,在可视区域外的dom,进行删除;

这种方式在PC上是没什么问题,但是在移动端,就会有layout,重绘重排;

优化方案四:使用canvas绘制列表

将列表绘制到canvas上,这样整个列表就是一个dom元素;只绘制可视区域的列表项;

但是测试发现,小米手机问题是解决了,但是在三星手机上又有问题

通过canvas绘制列表可以减少绘制的条目,FPS会有很大的提升,但是由此也证明一些机型,单纯的canvas绘制操作上已经达到了性能瓶颈;渲染区域越大,性能越受限,而且canvas绘制的元素不支持无障碍化,不支持被读屏软件识别;

优化方案五:滚动依然使用模拟的滚动,滚动过程中,复用dom

这样,dom的个数只有可视区域内dom个数,与条目总的数目没有关系;

测试结果:

总结一些上面的五种优化方案;

你可能感兴趣的:(Web前端)