前端浏览器渲染优化

By Jordan Irabor | January 17 2019

原文

介绍

我们生活在一个强调快速提供网络服务的时代。由于web应用的负载传输不断增加,开发者必须采取最佳实践来确保数据包被即刻分发,以此提供给用户拉稀般的网络体验

如今被web开发广泛采用的最佳实践是图片压缩、代码压缩、代码打包(webpack打包)等等。这些实践已经被证明了能有效提高用户体验,如果开发者能够深入理解浏览器渲染原理的话,还可以优化性能以提高用户体验。

当我们在低端机子玩对GPU要求高的游戏的时候,我们会遇到一些卡顿——环境和游戏人物的卡顿。这种现象(虽然不那么明显)也会在web应用上出现;用户会在进行鼠标点击或滚动页面等的页面交互时感受到应用会有一两秒的卡顿,从而会中断用户的交互操作

在本文中,我们将讨论Web应用程序以每秒60帧的速度运行(最佳)的条件

什么进入了页面

在web应用上,每当页面发生变化,在浏览器内部发生的事情是这样的:浏览器为用户提供给了一个新的页面,以便用户浏览和交互。 这些帧出现(并且更新)的速率以每秒帧数(fps)来度量。如果浏览器花了太长时间来创建和渲染一张页面,fps就会下降,用户就会感觉卡顿

为了让浏览器稳定在60帧,开发者需要理解页面的渲染。下面是页面创建的五个步骤:

  1. 浏览器发起get请求

  2. 服务器返回html、css

  3. html被解析成dom

  4. css被解析成css对象模型(cssom)并与dom整合成渲染树

  5. 渲染树基本上由页面上显示的元素组成,并构成一个页面。

web应用的生命周期

在我们探索浏览器渲染路径并优化之前,我们需要学习应用的生命周期,因为这可以使我们做出明智的选择,以确定应用程序何时应该执行“繁重的工作”。 从而创造流畅的用户体验并增强用户满意度。

应用生命周期被分离出四个步骤:

1.Load

2.Idle

3.Animation

4.Response

Load

在用户操作web应用之前,web应用就已经被加载好了。 这是应用生命周期的第一步并且最重要的是这一步旨在将负载时间减少(理想情况下为1s)到尽可能小的数量。

Idle

应用加载完之后,经常是空闲状态;等待用户操作。应用加载完后到用户操作之前的这段空闲时间一般是50ms,开发者可以用这段时间坐一些耗时的工作, 例如加载一些用户很快要用到的资源(图片,视频)。

专业提示:显着减少加载时间的一个方法是首先加载UI的基础节点,然后在空闲阶段引入其他元素。

Animate

当用户开始操作应用并且空闲期已经结束时,应用程序必须对用户交互(和输入)做出适当的反应而没有任何明显的延迟。

提示:研究表明,需要大约十分之一秒(在与UI元素交互之后)才注意到卡顿。 因此,在此时间范围内响应用户输入是完美的。

当对用户交互的响应涉及某种动画时,可能会有一些挑战。为了将动画稳定到60帧每秒,每帧的限制为16ms - 这基本上是一秒除以60。

那么,浏览器的开销就应该时10ms到12ms。 实现此目的的一种方法是预先执行所有动画计算(在UI元素与之交互后的100ms内)。

浏览器渲染路径和优化空间

浏览器渲染路径有以下几个步骤:

1.js 2.样式计算 3.布局 4.绘制 5.合成层(Layer composition)

在网页上,页面发生改变(要么css要么js导致的),浏览器重新计算受影响元素的样式。如果元素的位置、形状等影响布局的地方发生更改, 浏览器将检查其他元素,创建新布局,重新绘制受影响的元素并将这些元素重新组合在一起。

但是,更改页面元素的某些属性可能会更改网页的渲染路径。例如,如果是绘画相关的属性,比如背景图片或者文字颜色这些有变动, 布局不会受影响因为这没有改变属性的位置和形状。其他属性更改可能会使布局生成和绘制脱离渲染管道。

我们将会展示一些关于浏览器渲染的一些优化。

js

js让开发者为用户提供优秀的动画效果和视觉体验,因此js成为web应用中必不可少的一部分。我们在上文对应用生命周期的讨论中提到, 浏览器有10ms~12ms去渲染每一个页面。为了减轻js在渲染管道的负担(译者:因为js执行时间过长导致一页面的渲染超过12ms), 在每个页面(帧)中尽可能早地执行所有JavaScript代码非常重要,因为它可能会触发渲染管道的其他区域。

使用 window.requesAnimationFrame() 方法很有必要,详情请看MDN文档

window.requestAnimationFrame()方法告诉浏览器您希望执行动画并请求浏览器调用指定的函数以在下一次重绘之前更新动画。 该方法将回调作为在重绘之前调用的参数

requestAnimationFrame方法使得浏览器能在正确的时机引入浏览器并且防止掉帧。下面是一个例子:

function doAnimation() {
    // Some code wizardry
    requestAnimationFrame(doAnimation); //schedule the next frame

}

requestAnimationFrame(doAnimation);
复制代码

在google开发者工具里的performance一栏中,允许开发者去记录每一页面(帧)绘制出来的情况,可以看到js在web应用中执行的情况

虽然requestAnimationFrame方法是非常重要的工具,但是还是会有些js代码非常耗费资源。 网站在我们的操作系统的主线程上运行,因此这些脚本可能会停止渲染管道的其他阶段的执行。要解决这个问题,我们可以使用Web worker。

web worker 能让我们在新的线程执行那些耗费资源的js代码。详情请看MDN文档

“有了web worker就简单了,我们可以把耗时的工作丢给后台进程。worker进程可以在不干扰用户界面的情况下执行任务。 一旦被创建,worker可以通过将消息发布到由该代码指定的事件处理程序来向创建它的JavaScript代码发送消息(反之亦然)。”

要使用此功能,你需要创建一个单独的JavaScript文件,你的主程序将生成一个Web worker。

样式计算

样式更改是任何Web应用程序渲染管道的关键部分,因为其元素所需的样式更改数量与样式重新计算的性能成本成正比。 可以查看Paul’s website来了解css样式影响渲染管道的细节。

除了样式变更的数量,选择器匹配应该考虑到我们的渲染优化列表中。选择器匹配是指确定应将哪些样式应用于任何给定DOM元素的过程。

某些样式可能比其他样式需要更多时间来处理,并且时间随着受一个或多个样式更改影响的元素数量的增加而增加。 解决此问题的合适方法是块元素修改器(BEM)方法。它提供了很好的性能优势,因为类匹配符合BEM方法,是现代浏览器中最快的选择器。

布局

一个主要的性能瓶颈是布局抖动。在js重新计算元素节点的位置和形状时,会导致浏览器重新布局。这样,当快速连续几次完成时,会导致强制同步布局。 在这篇文章中, Google的Paul Lewis,强调了可以采取的各种优化措施,以防止强制同步布局。

绘制

浏览器在开始填充屏幕像素时发生绘画。这包括在屏幕上绘制所有视觉元素(译者注:即在渲染树上的节点都会被绘制,不管它在不在屏幕视窗内), 这会生成多个平面,叫图层。当需要大面积绘制时,尤其是页面滚动时,绘制同样会导致性能问题。

绘制分析器,如上图。这让我们很容易就知道页面的哪些区域被绘制和什么时候绘制的。

第一个多选框,Paint flashing,勾上之后页面会以绿色高亮被重新绘制的部分。 这个频率可以告诉我们绘画是否会影响渲染管道上的性能问题。

我们看看上面这张图,可以看到在页面滚动时只有滚动条被重新绘制了。表明Scotch.io网站的主页上有做浏览器绘制的优化。

合成层(Layer Composition)

这是浏览器渲染管道的最后一步,它包含了重要的浏览器结构-图层(Layers)。浏览器引擎通过首先考虑样式和元素以及它们的排序方式来进行一些层管理。 然后尝试找出页面所需的图层并相应地更新图层树。

接下来,浏览器合成这些图层并在屏幕上显示它们。 当浏览器必须绘制彼此重叠的页面元素并且彼此存在于同一层中时,会出现由于绘制而导致的性能瓶颈。

要解决此问题,所涉及的元素必须存在于单独的层中。 这可以通过改变CSS属性并将其属性设置为transform来实现:

<element_to_promote> {
    will-change: transform;
}
复制代码

然而,应该注意的是,层的增加意味着花在层管理和合成上的时间增加。 使用Chrome开发工具,可以查看页面上的所有图层,如下所示:

打开chrome开发者工具,点击hamburger菜单按钮(三个竖着的点),选择more Tools,选择Layers。

转载于:https://juejin.im/post/5c5410b3e51d450135283ad2

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值