概览
如何构建用户体验友好的网站?
本文介绍如何体现出网页的快速这一方面
首次加载要快
关键渲染路径
从收到 HTML、CSS 和 JavaScript 字节到对其进行必需的处理,从而将它们转变成渲染的像素这一过程中有一些中间步骤,优化性能其实就是了解这些步骤中发生了什么 - 即关键渲染路径,优化前后对比示意:

看图我们就能联想到了按需加载。那么关键渲染路径到底是什么意思呢?
其实就是指一开始只加载一些必要的(关键)内容,要做到快速加载响应用户,也是我们所说的首屏时间越短越好。
为尽快完成首次渲染,我们需要最大限度减小以下三种可变因素:
- 关键资源的数量
- 关键路径的长度越短越好
- 关键字节的数量
一个页面包含 html css js img font等资源。那么我们为了首屏快速呈现,就要减少资源的加载了,因为css\js的下载会阻塞渲染线程解析dom,优化关键渲染路径的常规步骤如下:
- 对关键路径进行分析和特性描述:资源数、字节数、长度。
- 最大限度减少关键资源的数量:删除它们,延迟它们的下载,将它们标记为异步等。
- 优化关键字节数以缩短下载时间(往返请求次数)。
- 优化其余关键资源的加载顺序:您需要尽早下载所有关键资源,以缩短关键路径长度。
对资源进行分类,哪些是关键资源,哪些是非关键资源。如果都很关键,为了用户体验业界上出现了骨架屏、按需加载、异步加载、懒加载等比较成熟方案。
如何看你的关键渲染路径是否优化缩短了?
-
看DOMContentLoaded的时间;
DOMContentLoaded.png
-
chrome devtools 的Audits(或者最新版chrome改为lighthouse)可以帮你在本地测试网站性能,先categories那里选择测试的维度,再device选设备,最后点一下 Generate report 按钮就能生成报告,根据报告来看你的网站有什么问题
generate report.png
report.png
- 利用网站分析工具https://webpagetest.org/,或者https://developers.google.com/speed/pagespeed/insights/
这个可以分析你的在线网站在不同的设备不同的浏览器中的运行情况。
优化关键渲染路径之后,页面会进入等待交互的空闲期。接下来就是考虑渲染效果了。
渲染效果要快
一般设备屏幕刷新为60次/秒即60ftps,那么一帧大约为1000/60约16.66毫秒,但是实际上浏览器有整理工作要做,所以,开发者能够利用工作的时间只有10ms左右,如果超时了,就会出现帧率下降、屏幕抖动导致卡顿的现象,用户体验极差,所以我们有必要了解浏览器的渲染流程以便我们写出更好的实现效果的代码。
像素管道
像素至屏幕管道中的关键点,也是开发者拥有最大控制权的部分:指执行代码到改变屏幕显示之间的过程,在这个过程中的顺序大多数是走以下流程的
JavaScript > style > layout > paint >composite

JavaScript:指JavaScript执行一些dom操作,jquery的animate方法、css的transitions、animations、web animation API: requestAnimationFrame。
Style:样式计算,通过匹配选择器(如#header .nav)查找元素计算出哪些元素应用了哪些css规则的过程,最后计算出每个元素的最终样式。
Layout:在知道每一个元素应用哪些css规则之后,浏览器就开始计算这个元素所在的屏幕位置和占据空间的大小。
Paint: 绘制是填充像素的过程。它涉及绘制出文本、颜色、阴影,边框,基本上包括每个元素的可视化部分。绘制一般是在多个表面(层)上完成的。
Composite: 由于页面的各部分可能被绘制到多层,由此它们需要按正确顺序绘制到屏幕上,以便正确渲染页面。对于与另一元素重叠的元素来说,这点特别重要,因为一个错误可能使一个元素错误地出现在另一个元素的上层。
不一定每帧都总是会经过管道每个部分的处理。实际上,不管是使用 JavaScript、CSS 还是网络动画,在实现视觉变化时,管道针对指定帧的运行通常有三种方式:
- JavaScript > style > layout > paint >composite
5个步骤一个不少,场景:回流 - JavaScript > style > paint >composite
4个步骤,少了布局,场景:重绘 - JavaScript > style >composite
3个步骤,没有布局和绘制,如仅更改只由合成器处理的属性:如transform、opacity。
想知道更多的哪些属性的变化会触发哪些渲染步骤可以参考https://csstriggers.com/
上面这3种方式是我们实现页面效果的时候要考虑的,明显第3种方式要比前面的快,在实现效果时,如果能够走第3种方式就不要走第1、2种方式;
常见场景:
移动一个元素是改变它的transform translate 而不是改变它的left top属性。原理其实就是用了transform后这个元素层提升了。
js操作dom实现动画应当使用requestAnimationFrame 而不是 setTimeout , setInterval。
提升层、GPU加速
让元素有独立层的css属性:
- transform不为none
- will-change不为none
- filter不为none
- perspective不为none
- clip-path不为none
- position 为 fixed 或者 sticky
- opacity 小于1
- -webkit-overflow-scrolling 属性值为 touch 的元素
更多属性参考 https://developer.mozilla.org/zh-CN/docs/Web/Guide/CSS/Understanding_z_index/The_stacking_context
在需要动画的元素上可以考虑将其提升成一个独立层,但是也不要滥用,因为独立层太多的话也会消耗很多的内存、GPU资源。并不是布局的每个元素都包含一个图层,如果一个元素没有对应的层,那么这个节点就从属于父节点的图层。
如何查看一个页面有多少图层?在chrome devtools打开layers就知道了,下面只有5个layer,但是图层并不总是固定的,如果你操作了dom,css 改变了元素css可以提升层的属性将它提升为独立的层后,左边大的红色框那里就可以看到新增的图层。

RAIL模型评估性能
R: response; 响应 在100毫秒内响应用户操作
A: animation; 动画 在10毫秒内生成一帧
I: idle; 空闲 最大程度增加空闲时间,保证及时响应用户操作
L: load 加载 在1000毫秒内呈现内容
进一步解释如下图

其实还是围绕加载快、响应快、动画不掉帧这方面来衡量性能。
总结
本文围绕“快速”这个主题从而列举了关键渲染路径、渲染过程、如何评估性能等方面知识,希望您有所收获,谢谢。
网友评论