Web滚动性能优化实战
目录
[-]
- 我的前言
- 目录
- 介绍
- 滚动的原理
- 绘制分析
- 图像缩放
- 代价昂贵的样式
- Reflow与重绘
- 滚动事件防抖
- 结论
- 扩展阅读
我的前言
HTML5的API体系是重要知识,但是如何写出更高效的Web App对于从程序员进阶为高级程序员来说更为重要。技很重要,但是容易学会,术才是茫茫人海中鹤立鸡群,安生立命之本。
码农们容易吗?是的,我们必须要不断努力和学习才能进化为高级码农乃至顶级码农。
Web App的性能优化非常重要,之前我有过一篇LinkedIn的相关文章《用HTML5实现iPad应用无限平滑滚动》。
本文从另外一方面揭示了浏览器的渲染原理,就像开发Windows客户端要理解操作系统原理一样,有时候,性能优化不仅仅是了解HTML、JavaScript、CSS,浏览器的实现是墙外的另一角。
本文中所讲述的原理可以延伸应用到很多平台,例如如何保证Android应用屏幕滑动时的流畅性?有许多需要注意的点,例如不要在主线程中进行耗时的计算、不要采用过大过多的背景图片等等。
其实这个事情我们完全可以写一本书来详细阐述,也许。
目录
- 介绍
- 滚动的原理
- 绘制分析
- 图像缩放
- 代价昂贵的样式
- Reflow与重绘
- 滚动事件防抖
- 结论
- 扩展阅读
介绍
滚动的性能优化看起来不是一件很有必要的事情。毕竟,内容已有样式,所有资源已经或正在加载,我们为什么要关心滚动时会发生些什么呢?其实原因很简单,只要你滚动,浏览器就会把你的网站或者App绘制到屏幕上。这意味着我们有机会尽量减少浏览器的工作来最大限度地提高页面性能。
当用户使用你的应用时,平滑滚动实际上是用户体验里经常被忽视的重要组成部分。当滚动体验流畅时,使用这个应用会感觉到如丝般光滑和愉悦的体验,而卡顿则让人难以忍受。
滚动的原理
让我们来看看在滚动时有什么事情发生。要理解这点,我们必须简单介绍一下浏览器如何在屏幕上绘制内容。一切都始于DOM树,它实际上是页面内的所有元素。浏览器查看带样式的DOM树,找出滚动时它认为看起来是一样的元素。然后,它把这些元素组合在一起,并且为它们生成一张图片,这就是所谓的层。每一层需要被绘制和栅格化为一种结构,然后合成在一起,这就是你在屏幕上看到的图像。
如果你有对Chrome渲染的详细信息感兴趣,可以看看这篇概要(宇捷:在国内可以看看这篇)。
当你滚动页面时,浏览器可能会需要绘制这些层(有时也被称为合成层)里的一些像素。通过元素分组,当某个层的内容改变时,我们只需要更新该层的结构,并仅仅重绘和栅格化渲染层结构里变化的那一部分,而无需完全重绘。显然,如果当你滚动时,像视差网站(宇捷:关于视差网站,可以看看这篇文章,以及示例网站1、示例网站2、示例网站3,稍后我可能会介绍这种设计方式)这样有东西在移动时,有可能在多层导致大面积的内容调整,这会导致大量的绘制工作。
总之,少绘最佳。
绘制分析
理论说了这么多,让我们来看看实践中如何工作。你可以用Chrome浏览器的DevTools来看看这个演示页面。如果你打开时间轴面板(Timeline panel),设置为帧模式(frame mode),点击纪录按钮(record button),然后开始滚动,你可以看到一堆绿色的条。我录制了一段视频来展示你应该做什么和可以看到什么(宇捷:甚至在切换Tab时你也可以看见图形在变化)。
在时间线下方的列表中,你会看到全部绘制记录。这是Chrome绘制和栅格化页面合成层结构的过程。(所有绘制完成后,你还可以看到一些合成层的记录,这是所有这些已经更新的层为将在屏幕上显示进行合成准备)
Chrome DevTools里的绘制记录
在每一个绘制记录后,你可以看到绘制区域的尺寸,如果你滚动页面,Chrome将突出显示页面中需要重绘的区域。另一个查看重绘区域的方法是,通过右下角的小齿轮图标进入DevTools设置,在里面激活 “显示绘制矩形(show paint rectangles)”选项。这是我们得到的滚动时页面性能的第一个指标。提醒一下:你应该寻找最小的可能绘制区域。
在页面左侧菜单可见的情况下,绘制区域基本上是整个屏幕,性能会受到很大影响。原因是这时Chrome创建了多个需调整的区域。在这种情况下,整个横向的可视内容会进入视图,还有100%高的左侧菜单也会进入同一个合成层,所有这一切会合成为一个100%高、100%宽的区域。如果你使用页面上方的勾选框禁用侧边栏菜单,再次滚动,你会发现此时只需要重绘横向的细条,这会快上很多。
如果你想看看实际的例子,试试打开Google+,然后把侧边栏导航的样式从position: fixed修改为position: absolute。当然这会改变站点的行为,但是关键是通过切换风格,你可以看到真正性能的提升。你对此的反应可能是考虑以后应不应该使用position:fixed,但实际上所有这一切都依赖于环境和需求。最重要的是要能够测量和了解你的决定所带来的影响。
图像缩放
在基本的绘制记录外我们还得到了一些信息,尤其是和图像相关。 如果在记录时缩放页面,你会看到一些绘制记录允许展开来查看更多信息。这么做之后,你应该可以看到一些图像缩放记录。这正是它所揭示的:浏览器需要把缩放图像作为绘制工作的一部分。
Chrome DevTools的图像缩放记录
如果用CSS或者图像尺寸属性缩放了一张大图,你就更有可能看到这样的情况。 当然,浏览器重新缩放图像的次数,以及它需要这样做的频率,会影响页面的性能,因为它们发生在浏览器主线程,由此会阻塞其它任务。
因此,使用无需缩放的图像是非常重要的。可以从一个有趣的侧面说明这一点,缩放操作很多情况下是不可避免的,尤其是在移动设备上。在这种情况下你没有太多可以做的事情,但是你最好知道这会(并且极有可能)发生。有利的一面是,浏览器总是在改进中,尤其渲染更是一个热门的话题,所以你可以期望事情在未来的几个月内会变得更好。
因此综上所述,还有其它可能会影响滚动性能的因素:
- 代价昂贵的样式
- Reflow与重绘
- 滚动事件去抖
让我们来详细谈谈每一点。
代价昂贵的样式
首先要说的是,并非所有的样式都是一样的,一些效果例如盒阴影(box-shadow)和oft-quoted代价特别昂贵。原因很简单,因为它们相关的绘制代码比其它样式需要更长的时间来运行。这意味着,如果你使用了这些样式,而且需要经常重绘,你很可能遇到性能问题。第二点要说的是一切都会变化,所以现
补充:Web开发 , 其他 ,