「无限加载更多」带来的性能瓶颈

引子

相信很多前端都遇到过这样的需求,在一个页面中预加载一个列表数据,当浏览器滚动到底部之后加载更多数据,然后循环往复这个操作。不知道大家有没有想过这个问题,设备的内存是有限的,而操作系统分配给每一个程序的内存资源也是有限制的,假如我们一直把这个列表加载下去,会出现什么样的问题?

OK,我遇到问题了

其实我发现这个加载更多带来的性能瓶颈,并不是从加载更多这个功能本身得知的。而是从其他方面发现的。

在我们产品的首页 txbb.com/m在iPhone6上我发现slider组件滚动的那么顿呢,这个组件是自己写的zepto插件,在 西祠首页 也是用的它,西祠就很流畅,为什么它这么顿呢?后来我想起来,曾经我改过一次代码,是把类的形式转成了$.fn的形式,是不是这个原因呢?于是我重新写了一个页面,加载了这个slider组件,发现,很流畅!还有一个重点,我拿同事的安卓机发现还比iPhone6上要快一点

后来我猜到了是不是跟内存容量有关系,页面太大了。我用了一个笨的方法定位问题,我不停的删原来页面里的元素,当我删掉部分列表数据之后,问题瞬间暴露出来了,这个slider变快了!

呵呵,懂了,列表数据太多,用的内存太大,导致slider卡顿了。因为西祠的首页很简单,而我们现在的产品的首页数据很多,所以这是问题的关键所在。

找到问题之后,就是优化了,可是怎么优化呢?

淘宝M版带来的灵感

我直接想到在大淘宝的M版首页上也有这个类似的加载更多,于是我去了大淘宝首页看看,大淘宝的首页也有加载更多的列表,但是基本不怎么卡,这是为神马呢?

OK,开始调试他们的页面。我又惊奇了,发现淘宝首页的列表数据中的图片都是以background形式加载的而不是img的src,而且滚出视野的图片会被隐藏,搜噶!原来问题出在这里。

开始优化

说干就干,我模仿淘宝首页进行了代码重构,将我的加载更多列表也做了一样的优化:

  • 图片改为background
  • 滚出视野范围隐藏图片

速度顿时快了不少,但还是有点卡顿,我擦,这咋办,还卡,我郁闷了......

举一反三

我思考了一下,既然是把图片隐藏,它快了一些,那我干脆把滚出视野的dom元素都隐藏不就行了,不能用opacity,没意义,不能用display:none,影响高度,计算又带来代码复杂度的提升,怎么办呢?visibility:hidden

OK,进行了对滚出视野范围的元素 visibility:hidden 之后,slider组件立马快了,我很欣慰。优化成功!

遗留问题的猜测

为什么高大上的iOS卡,安卓却好一些?

我猜是因为iOS对app的内存分配的更加严格,而安卓却很慷慨,所以不会卡。

总结

在web前端制作加载更多数据的场景中,尤其是在移动端,内存资源非常珍贵,一些简单的优化都可能带来性能提升,一定要注意。

这次的优化工作得到了以下灵感:

  • img src 比 background 方式展示图片,使用到的内存资源可能会更多
  • 移动端的内存是有限的,在进行代码设计是要充分考虑有可能带来的性能瓶颈。
  • 图片很浪费内存!要小心!
  • visibility:hidden, display:none 都可以节约内存