第四十九期:闲聊前端性能优化

2022-07-15 10:27:42 浏览数 (1)

前端性能优化是一个老生常谈的话题,而且我们看到的很多文章介绍的也非常详细,但是这些内容如果自己不去思考,不去整理的话,一旦我们在实际的项目里真的需要去做这么一件事儿的话,到头来你会发现其实还是无从下手。

我们不妨按照这个思路去思考:

一,为什么需要性能优化?这是性能优化的目的。

二,在实施这个过程之前我们需要了解哪些方面的知识?性能优化的前提。

三,影响性能的因素有哪些?

四,处理性能优化我们可以采用哪些手段?

当我们的脑海里有了这四个问题之后,回过头来看,我们就应该知道如何去对我们的项目进行进一步的优化了。

性能优化的目的

简而言之,性能优化的目的就是让我们的应用运行的更快。页面加载到可交互以及可响应消耗的时间最少,滚动是否流畅,按钮是否可点击,弹框是否能快速打开?数据表格是否可以快速加载?这些都是我们的目的。

一言以蔽之,加快应用响应速度,增强用户体验。

浏览器加载页面的过程

这里聊一个非常常见的问题,浏览器加载页面的过程。相信很多人都遇到过这个问题,但是应该很少有人去思考为什么要问这样一个问题?

很简单,理解这个原理对于我们做性能优化非常有帮助。

先复习一下浏览器的工作原理。浏览器的工作原理大致有以下几个过程:导航-->响应-->解析-->渲染-->交互。

性能优化的一个重要目的就是缩短浏览器完成这些过程所花费的时间。这就需要我们对这些过程的细节多少有些了解。

比如:当我们请求某个页面时,如果浏览器之前没有访问过这个域名,那么就需要进行DNS解析,解析为一个IP地址,当第一次初始化完成之后,这个IP地址可能会被缓存一段时间,这样就可以直接从缓存检索IP地址,而不再是通过域名服务器进行解析。

并且,通过域名加载页面通常仅需要一次DNS解析,但是如果应用中的图片,文本,脚本,样式不在同一个域名下,则需要多次DNS解析。

一旦完成DNS解析,以及HandShake,建立了网络连接,浏览器会代表用户发送一个get请求,通常是一个html文件。服务器收到请求,则对其进行回复。

TCP有一个慢开始、14KB规则。第一个响应包是14kb大小,这是慢开始的一部分,慢开始是一种均衡网络连接速度的算法。逐渐增加发送数据的数据量达到网络的最大带宽。

收到初始包之后,服务器会将下一个包的大小加倍到大约28kb,依次是前一个包的两倍,直至待到预定的阈值或者遇到网络拥堵。

这也是为什么性能优化会将14kb作为初始响应优化的重点。

构建Dom树。DOM节点的数量越多,构建DOM树所需的时间就越长。当解析器发现非阻塞资源时,比如一张图片,浏览器就会请求这些资源并且继续解析。当遇到CSS文件时解析亦可以继续进行,但是对于<script>标签,他会阻塞渲染并停止解析。

同时一个值得注意的问题是,等待获取CSS的过程不会阻塞HTML的解析,但是它有可能阻塞JS代码,因为js代码经常用来查询css属性。

关键渲染路径

关键渲染路径是浏览器将 HTML,CSS 和 JavaScript 转换为屏幕上的像素所经历的步骤序列。优化关键渲染路径可提高渲染性能。关键渲染路径包含了 文档对象模型 (DOM),CSS 对象模型 (CSSOM),渲染树和布局。

生成文档对象模型 (DOM),CSS 对象模型 (CSSOM),渲染树和进行布局,都是需要花费时间的。我们要做的就是尽量减少这些过程花费的时间。

对于Dom来说我们都知道,节点数量越多,花费的时间就越长,对应的我们就可以减少Dom数量。

对于CSSOM来说,从选择器性能的角度来讲,更少的选择器肯定比更多的选择器要快。例如,.foo {} 是比 .bar .foo {} 更快的因为当浏览器发现 .foo ,接下来必须沿着 DOM 向上走来检查 .foo 是不是有一个祖先 .bar。越是具体的标签浏览器就需要更多的工作,但这样的弊端未必值得优化。

更具体的规则更昂贵因为它必须遍历更多的 DOM 树节点,但这所带来的额外的消耗通常很小。

常用的两种策略

这里主要介绍这几个手段:一,dns预解析。二,延迟加载。

当浏览器从(第三方)服务器请求资源时,必须先将该跨域域名解析为 IP地址,然后浏览器才能发出请求。此过程称为 DNS解析。DNS 缓存可以帮助减少此延迟,而 DNS解析可以导致请求增加明显的延迟。对于打开了与许多第三方的连接的网站,此延迟可能会大大降低加载性能。

dns-prefetch 可帮助开发人员掩盖 DNS解析延迟。HTML 元素 通过 dns-prefetch的 rel 属性 (en-US)值提供此功能。然后在 href属性中指要跨域的域名:

代码语言:javascript复制
<link rel="dns-prefetch" href="https://909500.club.com/"> 

请记住以下三点:首先,dns-prefetch 仅对跨域域上的 DNS查找有效,因此请避免使用它来指向您的站点或域。这是因为,到浏览器看到提示时,您站点域背后的IP已经被解析。

其次,还可以通过使用 HTTP链接字段将 dns-prefetch(以及其他资源提示)指定为 HTTP标头:

第三,考虑将 dns-prefetch 与 preconnect(预连接)提示配对。尽管 dns-prefetch 仅执行 DNS查找,但preconnect 会建立与服务器的连接。如果站点是通过HTTPS服务的,则此过程包括DNS解析,建立TCP连接以及执行TLS握手。将两者结合起来可提供进一步减少跨域请求的感知延迟的机会。您可以安全地将它们一起使用,如下所示:

代码语言:javascript复制
<link rel="preconnect" href="https://909500.club.com/" crossorigin>
<link rel="dns-prefetch" href="https://909500.club.com/">

延迟加载(懒加载) 是一种将资源标识为非阻塞(非关键)资源并仅在需要时加载它们的策略。这是一种缩短关键渲染路径长度的方法,可以缩短页面加载时间。

延迟加载可以在应用程序的不同时刻发生,但通常会在某些用户交互(例如滚动和导航)上发生。

延迟加载的一个常见的场景就是代码拆分。即webpack中的code splitting。

而对于css的优化,除了删除不必要的css之外,一个非常不常见的技巧就是使用媒体查询。

默认情况下,浏览器假设每个指定的样式表都是阻塞渲染的。通过添加 media属性附加媒体查询,告诉浏览器何时应用样式表。当浏览器看到一个它知道只会用于特定场景的样式表时,它仍会下载样式,但不会阻塞渲染。通过将 CSS 分成多个文件,主要的 阻塞渲染 文件(本例中为 styles.css)的大小变得更小,从而减少了渲染被阻塞的时间。

0 人点赞