在浏览器地址栏输入一个URL后,浏览器会向服务器发送请求,服务器正确返回数据后,数据以页面的形式被渲染至浏览器上,这是一个非常常见的场景,如果等待时间较长,用户体验会非常不好,所以这个时候就需要做性能优化。
性能优化的目的就是尽量缩小从请求到成功渲染的时间,从请求到成功渲染会经历DNS解析
、建立TCP连接
、发送HTTP请求并得到响应
、页面渲染
,所以可以从以下几个角度出发,去实现前端性能优化。
-
DNS解析
- 适当的域名划分,减小服务器并行处理,切分组件到各个域
-
HTTP请求
-
精简JavaScript和css,合并、压缩脚本文件和样式文件,小图标可以做成雪碧图,避免多次访问图片资源
-
合理使用浏览器缓存,对于重复内容,强制浏览器在本地缓存这些文件,(浏览器缓存
) -
使用压缩组件(webpack、gulp)
-
避免重定向
-
CDN托管
CDN的全称是Content Delivery Network,即内容分发网络。其目的是通过在现有的Internet中增加一层新的网络架构,将网站的内容发布到最接近用户的网络“边缘”,使用户可以就近取得所需的内容,提高用户访问网站的响应速度。
用户在自己的浏览器中输入要访问的网站的域名,浏览器向本地DNS请求对该域名的解析,本地DNS将请求发到网站的主DNS,主DNS根据一系列的策略确定当时最适当的CDN节点,并将解析的结果(IP地址)发给用户,用户向给定的CDN节点请求相应网站的内容。
-
添加Expire/Cache-Control头
一般应用中,我们对静态内容添加Expires,对动态内容设置Cache-Control。假设两者均设置为时间常数的话,前者会被后者覆盖掉
-
-
浏览器响应速度
-
图片,JavaScript预加载,懒加载
-
JavaScript放在底部,JavaScript异步加载(defer和async属性)
defer和asyns的区别:
<script src="script.js"></script>
没有
defer
或async
,浏览器会立即加载并执行指定的脚本,“立即”指的是在渲染该script
标签之下的文档元素之前,也就是说不等待后续载入的文档元素,读到就加载并执行。<script async src="script.js"></script>
有
async
,加载和渲染后续文档元素的过程将和script.js
的加载与执行并行进行(异步)。<script defer src="myscript.js"></script>
有
defer
,加载后续文档元素的过程将和script.js
的加载并行进行(异步),但是script.js
的执行要在所有元素解析完成之后,DOMContentLoaded
事件触发之前完成。 -
css放在顶部,放在底部可能会出现白屏或者无样式的内容闪烁
-
使用外部JavaScript和css
-
使用类名操作样式,而不是直接操作样式,缓存某些属性
-
浏览器渲染机制
基本概念:
- DOM(Document Object Model),浏览器将HTML解析成树形的数据结构
- CSSOM(CSS Object Model),浏览器将css解析成树形的数据结构
- Render Tree,合并DOM和CSSOM,生成渲染树
- Layout,计算Render Tree每个节点的具体位置
- Painting,通过显卡将Layout后的节点内容分别显示在屏幕上
详细流程:
当浏览器获得HTML文件后,会自上而下的加载,并在加载过程中进行解析和渲染,在获取资源文件的过程中,如果遇到了外部CSS文件和图片,浏览器会另外发送一个请求,来获取CSS文件和相应的图片,这个请求时异步的,并不会影响HTML文件;如果遇到了JS文件,HTML文件会挂起渲染的过程,等待JS加载完毕后,HTML文件会再继续渲染(JS可能会影响DOM结构,可能会导致HTML资源白白加载,所以HTML要等待JS文件,为了网页加载的快一点,一般吧JS文件写在底部body标签内)。
tips: 回流和重绘分别就是触发了Layout和Painting环节
回流:引起DOM树重新计算的行为,以下操作会引起回流
- DOM的几何属性变化
- DOM树的结构变化,如节点的增减和移动
- 获得某些属性,如offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight、getComputedStyle() (currentStyle in IE)。所以,在多次使用这些值时应进行缓存
- 其他,如改变窗口大小,改变一些元素的样式
重绘:一个元素的外观变化引起的浏览器行为,例如改变visibility、outline、背景色等属性。浏览器会根据元素的新属性重新绘制,使元素呈现新的外观。重绘不会带来重新布局,并不一定伴随回流。
回流是非常容易影响性能的因素,所以合并多次改变样式的操作,使用类名操作,让需要多次改变的元素脱离文档流,需要获得哪些可能会引起浏览器回流的属性值时,缓存变量都可以优化性能。