前端性能
从输入url到页面展现发生了什么
- 浏览器地址输入url,按下回车
- DNS解析:将域名解析为ip
- TCP连接:三次握手
- 发生HTTP请求
- 服务器解析请求,返回HTTP报文
- 浏览器解析渲染页面
- 断开连接:TCP四次挥手
url
常见的URL是这样的:http://www.baidu.com,这个域名由三部分组成:协议名、域名、端口号,这里端口是默认所以隐藏。最常见的的协议是HTTP协议,除此之外还有加密的HTTPS协议、FTP协议、FILe协议等等。如HTTP默认端口80,HTTPS默认端口443
DNS解析
DNS工作原理:
第一步:客户机提出域名解析请求,并将该请求发送给本地的域名服务器。
第二步:当本地的域名服务器收到请求后,就先查询本地的缓存,如果有该纪录项,则本地的域名服务器就直接把查询的结果返回。
第三步:如果本地的缓存中没有该纪录,则本地域名服务器就直接把请求发给根域名服 务器,然后根域名服务器再返回给本地域名服务器一个所查询域(根的子域) 的主域名服务器的地址。
第四步:本地服务器再向上一步返回的域名服务器发送请求,然后接受请求的服务器查 询自己的缓存,如果没有该纪录,则返回相关的下级的域名服务器的地址。
第五步:重复第四步,直到找到正确的纪录。
第六步:本地域名服务器把返回的结果保存到缓存,以备下一次使用,同时还将结果返 回给客户机
DNS应用
1、 CDN (Content Delivery Network) 就是利用DNS的重定向技术,DNS服务器会返回一个跟 用户最接近的点的IP地址给用户,CDN节点的服务器负责响应用户的请求,提供所需的内容。
2、dns-prefetch 是一种 DNS 预解析技术。当你浏览网页时,浏览器会在加载网页时对网页中的域名进行解析缓存,这样在你单击当前网页中的连接时就无需进行 DNS 的解析,减少用户等待时间,提高用户体验
TCP三次握手、四次挥手
1. 客户端请求建立连接,发送SYN=1请求序号标志
2. 服务端发送SYN请求标志,发送确认序号标志ACK=1
3. 客户端发送ACK=1确认序号标志
1. 客户端发送FIN=1连接释放序号标志
2. 服务端发送ACK=1确认序号标志
3. 服务端发送FIN=1释放连接序号标志
4. 服务端发送ACK确认序号标志
HTTP请求
组成:
请求报文由请求行、请求头和请求体三部分组成。
1、请求行包含请求方法、url和协议版本。
2、请求头包含请求的附加信息,
3、请求体主要是请求参数(Query String Parameters)。
请求方式:
GET:用于请求访问已经被URI(统一资源标识符)识别的资源,可以通过URL传参给服务器
POST:用于传输信息给服务器,主要功能与GET方法类似,但一般推荐使用POST方式
PUT:传输文件,报文主体中包含文件内容,保存到对应URI位置
HEAD:获得报文首部,与GET方法类似,只是不返回报文主体,一般用于验证URI是否有效
DELETE:删除文件,与PUT方法相反,删除对应URI位置的文件
OPTIONS:查询响应URI支持的HTTP方法
GET和POST的区别
1、get重点在从服务器上获取资源,post重点在想服务器发送数据;
2、 get传输数据是通过URL请求,以filed(字段)=value的形式,置于URL后,并用”?”连接, 多个请求数据之间用“&”连接,这个过程用户是可见的,post是放在请求体内
3、 get传输量小,因为受URL长度限制,但效率较低/post可以传输大量数据,所以上传文件时只能用post方式
4、get是不安全的,因为URL是可见的,可能会泄露私密信息,如密码等
状态码:
1XX:接收信息正在处理
2XX:正常处理完毕(200请求成功)
3XX:重定向
301 永久重定向
302 临时重定向
4XX:客户端错误
400:语法错误(参数不对)
401:未认证
403:禁止访问
404:资源未找到
5XX:服务器错误
500:服务器出错
503:服务器繁忙
注意:
在发送HTTP请求的过程中,要先考虑浏览器缓存情况。缓存分为强制缓存和协商缓存。
开启gzip压缩:设置content-encoding:gzip
浏览器解析渲染页面
1、HTML解析,处理HTML标记并构建DOM树。
2、CSS解析,处理CSS标记并构建CSSOM树。
3、将DOM树和CSSOM合并称render tree(渲染树)。将每条css规则按照【从右至左】的方式在dom树上进行逆向匹配,然后生成具有样式规则描述的渲染树。
4、渲染树布局,计算每个节点的集合信息。包括repaint和reflow。
5、渲染树绘制,将每个节点绘制到屏幕上。
重绘与重排(重排 又叫 回流)
1、重排 (html改变) 一般是位置,大小,节点变化引起文档空间变化时发生的。
引起重排:
添加或删除可见的DOM元素
元素的位置发生变化
元素的尺寸发生变化(包括外边距、内边框、边框大小、高度和宽度等)
内容发生变化,比如文本变化或图片被另一个不同尺寸的图片所替代。
页面一开始渲染的时候(这肯定避免不了)
浏览器的窗口尺寸变化(因为回流是根据视口的大小来计算元素的位置和大小的)
2、重绘(css改变)一般是颜色等不引起文档结构变化时发生的。
简单粗暴的优化策略
⽂件加载的更少
1、 web缓存,CDN缓存
2、 图⽚优化
3、静态⽂件优化
4、 浏览器优化
5、⽂件合并压缩等雅⻁军规常规操作
代码执⾏的更少
1、节流防抖
2、按需执⾏
3、回流重绘
4、框架优化(⽐如vue3的静态标记)
前端性能监控
关键性能指标分析
FP(全称“First Paint”,翻译为“首次绘制”) 是时间线上的第一个“时间点”,它代表浏览器第一次向屏幕传输像素的时间,也就是页面在屏幕上首次发生视觉变化的时间。
注意:FP不包含默认背景绘制,但包含非默认的背景绘制。
FCP(全称“First Contentful Paint”,翻译为“首次内容绘制”),顾名思义,它代表浏览器第一次向屏幕绘制 “内容”。
注意:只有首次绘制文本、图片(包含背景图)、非白色的canvas或SVG时才被算作FCP。
FMP(全称“First Meaningful Paint”,翻译为“首次有效绘制”) 表示页面的“主要内容”开始出现在屏幕上的时间点。它是我们测量用户加载体验的主要指标。
注意:FMP本质上是通过一个算法来猜测某个时间点可能是FMP,所以有时候不准。
TTI(全称“Time to Interactive”,翻译为“可交互时间”) 表示网页第一次 完全达到可交互状态 的时间点
FP、FCP、FMP、TTI之间的比较。
性能分析工具
Chrome DevTool
在 Chrome 中,我们打开 Chrome 调试面板,进入 performance 界面
左上侧的位置有几个重要按钮
完成之后就会出现以下的界面
第一部分:controls
第二部分:重要参数,这一部分我们称之为 Overview 窗格,我们可以看到 FPS, CPU, NET 在页面加载时候的变化。
FPS:每秒帧数,绿色竖线越高, FPS 越高,我们应该关注红色部分,这说明我们的页 面很可能出现卡顿现象,另外 60 是一个比较理想的值。
CPU: CPU 资源。
NET: 每条彩色横杆代表一种资源,横杆越长,检索资源所需要的越长。
第三部分:火焰图
1)横轴表示加载的时间。
2)纵轴表示事件(线程)的执行顺序,先是上面的执行再到下面的,我们要特别注意 红色的三角部分。
第四部分:Summary 部分,可以看到 CPU 中中的资源分配
定位问题
其他性能分析工具
chrome开源工具Lighthouse
Performance API
W3C发布导航计时(Navigation Timing 2)的标准工作草案,该规范定义了一个统一的接口,存储和获取与网页导航的性能度量数据
常用API
performance.now(),返回performance.navigationStart至当前的毫秒数 //用performance.now()检测for循环的执行时间(毫秒) var st = performance.now(); for (var o = 0; o < 10000; o ++) { console.log(o) } var end = performance.now();} console.log(`for时间${end - st}`); // for时间1155.9950000373647 performance.navigation责纪录用户行为信息,只有两个属性 type:网页的加载来源,可能有4种情况 0:网页通过点击链接、地址栏输入、表单提交、脚本操作等方式加载,相当于常数 1:网页通过“重新加载”按钮或者location.reload()方法加载 2:网页通过“前进”或“后退”按钮加载 255:任何其他来源的加载 redirectCount:表示当前网页经过了多少次重定向跳转 performance.getEntries()返回包含了所有静态资源的数组列表,接收一个可选的参数options进行过滤,options支持的属性有name,entryType,initiatorType。 performance.mark()自定义添加标记的时间, 方便我们计算程序的运行耗时。 // 执行前做个标记 window.performance.mark('markStart'); // do ... window.performance.mark('markEnd'); // 测量两个标记之间的测量距离 window.performance.measure('measure1', 'markStart', 'markEnd'); // 看下保存起来的标记 mark var marks = window.performance.getEntriesByType('mark'); // 看下保存起来的测量 measure var measure = window.performance.getEntriesByType('measure'); // 清除指定标记 window.performance.clearMarks('markStart'); // 清除所有标记 window.performance.clearMarks(); // 清除指定测量 window.performance.clearMeasures('measure1'); // 清除所有测量 window.performance.clearMeasures(); performance.timing提供了在加载和使用当前页面期间发生的各种事件的性能计时信息 计算各种时间公式 var t = performance.timing; var rdTime = t.redirectEnd - t.redirectStart;//重定向时间
var dnsTime = t.domainLookupEnd - t.domainLookupStart;//DNS耗时
var tcpTime = t.connectEnd - t.connectStart//TCP连接之间
var httpTime = t.TimeresponseEnd - t.responseStart//HTTP请求耗时
var whiteTime = t.responseStart - t.navigationStart//白屏时间
var domReadyTime = t.domContentLoadedEventEnd - t.navigationStart //domReady时间
var onloadTime = t.loadEventEnd - t.navigationStart//onload时间
框架性能优化(Vue)
编码阶段
- 尽量减少data中的数据,data中的数据都会增加getter和setter,会收集对应的watcher;
- 如果需要使用v-for给每项元素绑定事件时使用事件代理;
- SPA 页面采用keep-alive缓存组件;
- 在更多的情况下,使用v-if替代v-show;
- key保证唯一;
- 使用路由懒加载、异步组件;
- 防抖、节流;
- 第三方模块按需导入;
- 长列表滚动到可视区域动态加载;
- 图片懒加载;
用户体验:
- 骨架屏;
- PWA;
- 还可以使用缓存(客户端缓存、服务端缓存)优化、服务端开启gzip压缩等。
SEO优化
- 预渲染;
- 服务端渲染SSR;
打包优化
- 压缩代码;
- Tree Shaking/Scope Hoisting;
- 使用cdn加载第三方模块;
- 多线程打包happypack;
- splitChunks抽离公共文件;