前端开发必须了解的浏览器渲染性能

微信小程序的前端开发
h5微信支付前端开发教程
微信开发 前端 后端

首先我们要明确的问题就是,一个网站除了样式好看,功能简单明了等限制用户浏览量的因素之外,还有什么原因是限制你的网站流量的原因。
####渲染性能
在网站资源加载时,大多数用户关心的并不是网站如何加载,而是网站的加载速度,如果一个网站10秒,20秒,甚至30秒都无法加载成功,我相信没有那个用户会继续停留在这个网页上,所以我们必须要思考的问题就是,怎样的网站是顺畅的。下面的是google提出的数据模型:

Respond:0 – 100ms,视窗一般需要在这个时间段响应用户,超过这个时间段,用户就会感觉到延时。

Animation:0~16ms,屏幕每秒刷新60次,16ms 代表的是每一帧的时间。用户是非常关注动画的,当动画失帧很容易引起用户察觉。所以动画一般要控制在60FPS。
Idle:最大化主进程的空闲时间,这样可以及时响应用户输入。
Load:内容需要在1000ms 内加载出来,超过1000ms 会觉得加载缓慢。
如果想到达上面的性能需求我们可以从优化浏览器的渲染过程入手,首先让我们从浏览器解析一个页面来开始分析
转化: 浏览器从磁盘或网络读取 html 的原始字节,浏览器会将这段原始文件按照相应编码规范进行解码(现在一般为 utf – 8)。
符号化:根据 W3C 标准转化为对应的符号(一般在尖括号内)。
DOM 构建:html 解析器会解析其中的 tag 标签,生成 token ,遇到 cssjs 会发送相应请求。HTML 解析时阻塞主进程的,css 一般也是阻塞主进程的(媒体查询时例外),也就是说它们在解析过程中是无法做出响应的。而 js 手动添加 async 后达到异步加载,根据 token 生成相应 DOM 树。
CSSOM 构建,添加 css 样式生成 CSSOM 树。
渲染树构建,从 DOM 树的根节点开始,遍历每个可见的节点,给每个可见节点找到相应匹配的 CSSOM 规则,并应用这些规则,连带其内容及计算的样式。
样式计算,浏览器会将所有的相对位置转换成绝对位置等一系列的样式计算。
布局,浏览器将元素进行定位、布局。
绘制,绘制元素样式,颜色、背景、大小、边框等。
合成,将各层合成到一起、显示在屏幕上。

####优化JavaScript的执行

函数的输入事件处理

首先,我们要知道的一个事实就是浏览器是由多个处理进程的:Compositor、Tile Worker、Main。当用户进行输入操作(滚动、点击等),如滚动时,Compositor 进程会接收到这个事件(实际它可以接受任何用户输入事件),如果可以的话,它将不会通知主进程,直接说:滚吧,牛宝宝。于是,页面就滚动了。当然,这其中包含更新层定位以及让 GPU 绘制帧,而主线程处于空闲状态。但是,事情往往并非如此。如果输入事件上绑定了 js 处理事件的话,Compositor 进程就没办法主动跳过主进程了。
js 处理事件过长时,输入事件的响应会一直处于阻塞状态,直到 js 处理完成。当响应超过 100ms 时,用户就会感受到延时。所以当处理用户事件时,我们应该做到:

避免长时间的 JS 执行。
避免在处理中改变样式。因为样式改变会引起后面布局、绘制、合成等操作。
对用户输入进行消抖。
    使用 requestAnimationFrame,将 setTimeout 换成 requestAnimationFrame,因为 setTimeout 时间控制可能造成在一帧的中间,目前各浏览器对 requestAnimationFrame 的支持已经比较好了。
    使用 web Workers,将复杂计算的 JS 采用 web Workers 进行处理。
    减少垃圾回收,垃圾回收是一个容易被忽略的问题,因为垃圾回收的时间是不受控制的,它可能在一个动画的中途,阻塞动画的执行,更理想的情况是在循环中复用对象。

####样式优化
添加或移除一个 DOM 元素、修改元素属性和样式类、应用动画效果等操作,都会引起 DOM 结构的改变,从而导致浏览器需要重新计算每个元素的样式、对页面或其一部分重新布局(多数情况下)。
计算样式的第一步是创建一套匹配的样式选择器,浏览器就是靠它们来对一个元素应用样式的。第二步是根据匹配的样式选择器来获取对应的具体样式规则,计算出最终具体有哪些样式是要应用在 DOM 元素上的。所以,你只需要记住要减小选择器的复杂性,减少无效元素,从而减小样式的计算量
####布局优化
避免触发布局
目前,transform 和 opacity 只会引起合成,不会引起布局和重新绘制。整个流程中比较耗费性能的布局和绘制流程将直接跳过,性能显然是很好的。其他的 css 属性改变引起的流程会有所不同,有些属性也会跳过布局,具体可以查看 css Triggers。所以,优化的第一步就是尽可能避免触发布局。
避免快速连续的布局
还有一种情况比强制同步布局更糟:连续快速的多次执行它
javascript 代码

function resizeAllParagraphsToMatchBlockWidth() {
    // Puts the browser into a read-write-read-write cycle.
    for (var i = 0; i < paragraphs.length; i++) {
        paragraphs[i].style.width = box.offsetWidth + ‘px’
    }
}

上述代码对一组段落标签执行循环操作,设置 p 标签的width属性值,使其与 box 元素的宽度相同。看上去这段代码是没问题的,但问题在于,在每次循环中,都读取了 box 元素的一个样式属性值,然后立即使用该值来更新 p 元素的 widt h属性。在下一次循环中读取 box 元素 offsetwidth 属性的时候,浏览器必须先使得上一次循环中的样式更新操作生效,也就是执行布局过程,然后才能响应本次循环中的样式读取操作。布局过程将在每次循环中发生。优化代码:
javascript 代码

var width = box.offsetWidth
function resizeAllParagraphsToMatchBlockWidth() {
    for (var i = 0; i < paragraphs.length; i++) {
        // Now write.
        paragraphs[i].style.width = width + ‘px’
    }
}
微信公众号前端开发
微信公众号 前端开发
开发微信小程序前端
赞(0)
前端开发者 » 前端开发必须了解的浏览器渲染性能
64K

评论 抢沙发

评论前必须登录!