前端性能优化【进阶篇】
共 7289字,需浏览 15分钟
·
2021-03-07 04:04
关注 前端瓶子君,回复“交流”
加入我们一起学习,天天进步
作者:前端学苑 公号 / 前端小贾 (本文来自作者投稿)
衡量网页的性能是一个比较琐碎的事情,因为没有某一个指标或数字可以直接告诉我们网页的性能怎样。优化的目的在于让页面加载的更快,对用户操作响应更及时,为用户带来更好的用户体验,对于开发者来说优化能够减少页面请求数,能够节省资源。
简短的概括:
1、前端性能优化
2、前端性能监控
3、框架性能优化
一、前端性能优化
1、从输入url到页面展现发生了什么?(万能面试题)
2、网络优化
3、浏览器优化
详细如下:
从输入url到页面展现发生了什么?
(万能面试题)
1)浏览器的地址栏输入URL并按下回车;
2)DNS 解析:将域名解析成 IP 地址;
3)TCP 连接:TCP 三次握手;
4)发送 HTTP 请求;
5)服务器处理请求并返回 HTTP 报文;
6)浏览器解析渲染页面;
7)断开连接:TCP 四次挥手
说完整个过程的几个关键点后我们再来展开的说一下。
1、URL
我们常见的URL是这样的:http://www.baidu.com,这个域名由三部分组成:协议名、域名、端口号,这里端口是默认所以隐藏。最常见的的协议是HTTP协议,除此之外还有加密的HTTPS协议、FTP协议、FILe协议等等。如HTTP默认端口80,HTTPS默认端口443。说到这里可能有的面试官会问你同源策略,以及更深层次的跨域的问题。
2、DNS 解析 ( * 网络优化 )
在浏览器输入网址后,首先要经过域名解析,因为浏览器并不能直接通过域名找到对应的服务器,而是要通过 IP 地址。
1) IP 地址
IP 地址是指互联网协议地址,是 IP Address 的缩写。IP 地址是 IP 协议提供的一种统一的地址格式。
2) 域名解析定义
DNS 协议提供通过域名查找 IP 地址,或逆向从 IP 地址反查域名的服务。DNS 是一个网络服务器,我们的域名解析简单来说就是在 DNS 上记录一条信息记录。
3) 浏览器如何通过域名去查询 URL 对应的 IP 呢?
DNS域名解析分为递归查询和迭代查询两种方式,现一般为迭代查询。
DNS 应用
1) CDN (Content Delivery Network) 就是利用DNS的重定向技术,DNS服务器会返回一个跟 用户最接近的点的IP地址给用户,CDN节点的服务器负责响应用户的请求,提供所需的内容。
2) dns-prefetch 是一种 DNS 预解析技术。当你浏览网页时,浏览器会在加载网页时对网页中的域名进行解析缓存,这样在你单击当前网页中的连接时就无需进行 DNS 的解析,减少用户等待时间,提高用户体验。
OSI参考模型与TCP/IP四层模型
3、TCP 连接
客户端和服务端建立TCP连接需要三次握手。过程如下:
1) 客户端发送一个带 SYN=1,Seq=X 的数据包到服务器端口(第一次握手,由浏览器发起,告诉服务器我要发送请求了)
2) 服务器发回一个带 SYN=1, ACK=X+1, Seq=Y 的响应包以示传达确认信息(第二次握手,由服务器发起,告诉浏览器我准备接受了,你赶紧发送吧)
3) 客户端再回传一个带 ACK=Y+1, Seq=Z 的数据包,代表“握手结束”(第三次握手,由浏览器发送,告诉服务器,我马上就发了,准备接受吧)
说明:
ACK:确认标识,用于表示对数据包的成功接收。
SYN:同步标识,表示TCP连接已初始化。
三次握手的目的:为了防止已经失效的连接请求报文段突然又传送到了服务器端,从而产生错误。
4、发送HTTP请求 ( * 网络优化 )
请求报文由请求行、请求头和请求体三部分组成。
1)请求行包含请求方法、url和协议版本。
2)请求头包含请求的附加信息,由键值对组成。如Host:github.com、User-Agent:""、Connection:keep-alive以及Cookie。
3)请求体主要是请求参数(Query String Parameters)。
注意:在发送HTTP请求的过程中,要先考虑浏览器缓存情况。缓存又分为强制缓存和协商缓存。
详细资料:一文读懂,关于 “ HTTP ” 那些事
5、服务器处理请求并返回 HTTP 报文
每台服务器上都会安装处理请求的应用——Web server。常见的web server产品有apache、nginx、IIS、Lighttpd等。
6、浏览器解析渲染页面 ( * 浏览器优化 )
浏览器渲染过程
1)HTML解析,处理HTML标记并构建DOM树。
2)CSS解析,处理CSS标记并构建CSSOM树。
3)将DOM树和CSSOM合并称render tree(渲染树)。将每条css规则按照【从右至左】的方式在dom树上进行逆向匹配,然后生成具有样式规则描述的渲染树。
4)渲染树布局,计算每个节点的集合信息。包括repaint和reflow。
5)渲染树绘制,将每个节点绘制到屏幕上。
重绘与重排(重排 又叫 回流)
1)重排 (html改变) 一般是位置,大小,节点变化引起文档空间变化时发生的。
引起重排:
添加或删除可见的DOM元素
元素的位置发生变化
元素的尺寸发生变化(包括外边距、内边框、边框大小、高度和宽度等)
内容发生变化,比如文本变化或图片被另一个不同尺寸的图片所替代。
页面一开始渲染的时候(这肯定避免不了)
浏览器的窗口尺寸变化(因为回流是根据视口的大小来计算元素的位置和大小的)
2)重绘(css改变)一般是颜色等不引起文档结构变化时发生的。
注:重绘不一定导致重排,但重排一定会导致重绘。
7、断开连接:TCP 四次挥手
当数据传送完毕,需要断开 tcp 连接,此时发起 tcp 四次挥手。
1) 发起方向被动方发送报文,Fin、Ack、Seq,表示已经没有数据传输了。并进入 FIN_WAIT_1 状态。(第一次挥手:由浏览器发起的,发送给服务器,我请求报文发送完了,你准备关闭吧)
2) 被动方发送报文,Ack、Seq,表示同意关闭请求。此时主机发起方进入 FIN_WAIT_2 状态。(第二次挥手:由服务器发起的,告诉浏览器,我请求报文接受完了,我准备关闭了,你也准备吧)
3) 被动方向发起方发送报文段,Fin、Ack、Seq,请求关闭连接。并进入 LAST_ACK 状态。(第三次挥手:由服务器发起,告诉浏览器,我响应报文发送完了,你准备关闭吧)
4) 发起方向被动方发送报文段,Ack、Seq。然后进入等待 TIME_WAIT 状态。被动方收到发起方的报文段以后关闭连接。发起方等待一定时间未收到回复,则正常关闭。(第四次挥手:由浏览器发起,告诉服务器,我响应报文接受完了,我准备关闭了,你也准备吧)
TCP与UDP区别总结:
相同点:TCP和UDP都是网络层之上的,传输层协议,都能都能保护网络层的传输,双方的通信都需要开放端口,TCP和UDP中都存在复用和分用技术。
不同点:TCP是可靠传输的,UDP是不可靠传输的。
TCP VS UDP 对比:
简单粗暴的优化策略
1、⽂件加载的更少
1) 缓存,CDN (详细资料:解析Web缓存及其最佳实践)
2) 图⽚优化
3) 静态⽂件优化
4) 浏览器优化
5) ⽂件合并压缩等雅⻁军规常规操作
2、代码执⾏的更少
1)节流防抖 (详细资料:彻底弄懂 “ 防抖 和 节流 ”)
2)按需执⾏
3)回流重绘
4)框架优化(⽐如vue3的静态标记)
5)html、css、javascript
二、前端性能监控
1、前端性能指标分析
2、关键性能指标统计
3、性能分析工具
详细如下:
前端性能指标分析
以 https://www.google.com.hk 为例,下图是使用Lighthouse(一个性能测评工具)捕获出的测评结果报告。
下图是使用Chrome浏览器的DevTools捕获出的加载性能结果报告。
从上面这两张性能测评报告中,我们会发现报告通常会给出很多个 “关键时间点” 来表示性能数据,单独的某个“时间点”无法体现出网页的性能,只有将它们与自身的产品类型相结合,综合评估,才能判断出网页的性能到底怎样。而我们要做的,就是读懂报告中的各种专业术语,并分辨出哪些因素影响了网页的加载性能。
关键性能指标统计
FP、FCP、FMP与TTI
从前面的评测报告中,我们会看到FP、FCP、FMP与TTI这几个字母很接近的术语,实际上他们的意思也非常接近,都表示浏览器在屏幕上渲染像素的时间点。
1)FP(全称“First Paint”,翻译为“首次绘制”) 是时间线上的第一个“时间点”,它代表浏览器第一次向屏幕传输像素的时间,也就是页面在屏幕上首次发生视觉变化的时间。
注意:FP不包含默认背景绘制,但包含非默认的背景绘制。
2)FCP(全称“First Contentful Paint”,翻译为“首次内容绘制”),顾名思义,它代表浏览器第一次向屏幕绘制 “内容”。
注意:只有首次绘制文本、图片(包含背景图)、非白色的canvas或SVG时才被算作FCP。
FP与FCP这两个指标之间的主要区别是:
FP是当浏览器开始绘制内容到屏幕上的时候,只要在视觉上开始发生变化,无论是什么内容触发的视觉变化,在这一刻,这个时间点,叫做FP。
FCP指的是浏览器首次绘制来自DOM的内容。例如:文本,图片,SVG,canvas元素等,这个时间点叫FCP。
3)FMP(全称“First Meaningful Paint”,翻译为“首次有效绘制”) 表示页面的“主要内容”开始出现在屏幕上的时间点。它是我们测量用户加载体验的主要指标。
注意:FMP本质上是通过一个算法来猜测某个时间点可能是FMP,所以有时候不准。
说明:
FMP 实现的三种方式:(需要扩展)
1、固定好dom的id,统计高度变化时间。
2、统计首屏dom的面积,计算占比 总结FMP。
3、dom变化趋势,来统计FMP。
计算占比 的思路 (需要扩展)
元素权重:宽*⾼*权重(img,video要⽐普通dom⾼);
进⼊⻚⾯开始记录,启⽤mutationobserver;
遍历domtree,根据可视区域⾯积,计算得分;
遍历⽗元素修正得分(⽗元素和⼦元素之和的最⼤值);
平均值,过滤出⽬标元素;
是否img(video,canvas等;
合集求出FMP
4)TTI(全称“Time to Interactive”,翻译为“可交互时间”) 表示网页第一次 完全达到可交互状态 的时间点。可交互状态指的是页面上的UI组件是可以交互的(可以响应按钮的点击或在文本框输入文字等),不仅如此,此时主线程已经达到“流畅”的程度,主线程的任务均不超过50毫秒。TTI很重要,因为TTI可以让我们了解我们的产品需要多久可以真正达到“可用”的状态。
图3给出了FP、FCP、FMP、TTI之间的比较。
W3C发布导航计时(Navigation Timing 2)的标准工作草案,该规范定义了一个统一的接口,存储和获取与网页导航和页面加载相关的高解析度的性能度量数据。
地址:https://www.w3.org/TR/navigation-timing-2/
如图:
性能分析工具
1)谷歌开发者工具的“性能”选项进行分析:performance
详细资料:性能优化篇 - Performance(工具 & api)
2)谷歌的Lighthouse工具(国内网络环境):基于 node(版本≥6)
安装:npm install -g lighthouse
运行使用:lighthouse <url> --view
例如:lighthouse https://www.baidu.com/ --view
3)如果可以翻墙的话:可以在 Chorome 网上应用商店中安装 - 网页性能优化的扩展程序:Lighthouse、PageSpeed Insights ;
4)在线网页性能分析工具(推荐)
https://tools.pingdom.com/
Pingdom是一个免费的网站速度测试工作,不仅是看起来非常棒,而且尽可能多的呈现出你的网站的各方面信息。
5)使用 Chrome 原生 lazyload 属性进行图片懒加载
chrome://flags/#enable-lazy-image-loading
复制它到 Chrome 浏览器的地址栏,然后找到如下选项,将其设置为「Enabled」。
例如:<img src="具体图片" alt="" lazyload="on">
说明:
auto 浏览器自行判断
on 开启懒加载
off 关闭懒加载
三、框架性能优化
1、Vue性能优化
2、长列表优化
3、用户体验优化
详细如下:
Vue性能优化
1、你都做过哪些Vue的性能优化?( 统计后的结果 )
1)编码阶段
尽量减少data中的数据,data中的数据都会增加getter和setter,会收集对应的watcher;
如果需要使用v-for给每项元素绑定事件时使用事件代理;
SPA 页面采用keep-alive缓存组件;
在更多的情况下,使用v-if替代v-show;
key保证唯一;
使用路由懒加载、异步组件;
防抖、节流;
第三方模块按需导入;
长列表滚动到可视区域动态加载;
图片懒加载;
2)用户体验:
骨架屏;
PWA;
还可以使用缓存(客户端缓存、服务端缓存)优化、服务端开启gzip压缩等。
3)SEO优化
预渲染;
服务端渲染SSR;
4)打包优化
压缩代码;
Tree Shaking/Scope Hoisting;
使用cdn加载第三方模块;
多线程打包happypack;
splitChunks抽离公共文件;
sourceMap优化;
说明:优化是个大工程,会涉及很多方面,这里申请另开一个专栏
2、vue1.X,vue2.X,vue3 框架分析性能 ( 还需要进一步学习 )
Vue1.x (特点:响应式)
没有vdom,完全的响应式,每个数据变化,都通过响应式通知机制来新建Watcher干活,项目规模变大后,过多的Watcher,会导致性能的瓶颈。
Vue2.x (特点:组件级响应式,组件内部vdom diff)
引入vdom,控制了颗粒度,组件层面走watcher通知, 组件内部走vdom做diff,既不会有太多watcher,也不会让vdom的规模过大,diff超过16ms,真是优秀。
Vue3 (特点:proxy做响应式:静态标记、按需更新)
先说结论,静态标记,upadte
性能提升1.3~2倍,ssr
提升2~3倍。
Vue3通过Proxy响应式+组件内部vdom+静态标记,把任务颗粒度控制的足够细致,所以也不太需要time-slice了。
长列表优化
1、vue-virtual-scroll-list优化长列表
虚拟列表的实现原理:只渲染可视区的 dom 节点,其余不可见的数据卷起来,只会渲染可视区域的 dom 节点,提高渲染性能及流畅性,优点是支持海量数据的渲染;
github地址:https://github.com/tangbc/vue-virtual-scroll-list
2、Object.freeze优化长列表
Object.freeze()方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。
对于data()或vuex中冻结的对象,vue不会做getter和setter的转换。因此对于一个不变的、大数据量的数组或Object数据来说,使用Object.freeze()可以有效地提升性能。
用户体验优化
使用骨架屏
骨架屏可以理解为是当数据还未加载进来前,页面的一个空白版本,一个简单的关键渲染路径。
一些项目,可能大部分数据都是从后端获取,网络请求是需要占用一定的时间的,所以用户一进来发现是空页面,所以这个时候可以使用骨架屏先加载一个轮廓,而不是让用户觉得这个页面挂了。
可以看一下上面的示例图,第一个为骨架屏,第二个为菊花图,第三个为无优化,可以看到相比于传统的菊花图会在感官上觉得内容出现的流畅而不突兀,体验更加优良。