From 1250b1e30bf4db2154c2b5a2fa85c374bca42ee2 Mon Sep 17 00:00:00 2001
From: gaofuhong <157297759@qq.com>
Date: Mon, 15 Jul 2024 16:18:25 +0800
Subject: [PATCH] feat: add performance optimization
---
docs/.vuepress/src/sideBarData.js | 4 +
.../1.\345\237\272\347\241\200.md" | 161 ++++++++++++++++++
2 files changed, 165 insertions(+)
create mode 100644 "docs/blog/frameSeries/performance/1.\345\237\272\347\241\200.md"
diff --git a/docs/.vuepress/src/sideBarData.js b/docs/.vuepress/src/sideBarData.js
index 09fc02c8..d9164e2f 100644
--- a/docs/.vuepress/src/sideBarData.js
+++ b/docs/.vuepress/src/sideBarData.js
@@ -66,6 +66,10 @@ const sideBarConfig = [
title: 'Nuxt',
folder: 'Nuxt',
},
+ {
+ title: '性能优化',
+ folder: 'performance',
+ },
]
},
{
diff --git "a/docs/blog/frameSeries/performance/1.\345\237\272\347\241\200.md" "b/docs/blog/frameSeries/performance/1.\345\237\272\347\241\200.md"
new file mode 100644
index 00000000..c82575cd
--- /dev/null
+++ "b/docs/blog/frameSeries/performance/1.\345\237\272\347\241\200.md"
@@ -0,0 +1,161 @@
+---
+title: 1.基础
+date: 2024-07-11
+sidebar: auto
+tags:
+ - 性能优化
+categories:
+ - 性能优化
+---
+
+## 1.Web性能介绍
+Web性能是客观的衡量标准,是用户对加载时间和运行时的直观体验。
+- 打开速度
+- 动画效果
+- 表单提交
+- 列表滚动
+- 页面切换
+...
+
+
+## 2.优化方案
+- 从发出请求到收到响应的优化,比如DNS查询、HTTP长连接、HTTP2、HTTP压缩、HTTP缓存等
+- 关键渲染路径优化,比如是否存在不必要的重绘和回流
+- 加载过程的优化,比如延迟加载,是否有不需要在首屏展示的非关键信息,占用了页面加载的时间
+- 资源优化,比如图片、视屏等不同的格式类型会有不同的使用场景,在使用的过程中是否恰当
+- 构件优化,比如压缩合并、基于webpack构件优化方案等
+...
+
+## 使用Chrome DevTools测试性能
+**网络请求阻止**
+- 打开方式:ctrl+shift+p -> show networl request blocking
+- 启用网络请求阻止
+- 添加组织规则
+
+**Coverage面板**
+通过Coverage面板监控并统计出网站应用运行过程中代码执行的覆盖率
+- 打开方式:ctrl+shift+p -> 搜索coverage(覆盖) -> 点击start instrumenting coverage and reload page
+统计结果包括:文件的字节大小、执行过程中已覆盖的代码字节数,以及可视化的覆盖率条形图
+
+**Memory面板(内存面板)**
+- 打开方式:ctrl+shift+p -> memory(内存)-> 点击显示内存
+
+**Performance面板(性能面板)**
+
+**FPS计数器**
+可在页面运行时提供对 FPS 的实时估计。
+- 打开方式:ctrl+shift+p -> FPS
+
+**Performance monitor**
+包括:CPU 占用率、JavaScript 内存使用大小、内存中挂的 DOM 节点数、JavaScript 事件监听次数及页面发生重绘与重排的处理时间等信息。
+
+## 前端页面的生命周期
+问题:在浏览器地址栏输入一个网址到页面渲染出来,中间都经历了什么
+1. 输入地址(例如: https://www.example.com),浏览器解析URL(浏览器解析输入的URL,将其分为不同的部分,如协议(https)、域名(www.example.com)、路径(/)、查询参数等)
+2. DNS解析(浏览器需要将域名转换为IP地址,这个过程称为DNS解析)
+- 浏览器缓存:首先,浏览器会检查其缓存中是否有对应的IP地址
+- 操作系统缓存:如果浏览器缓存中没有,浏览器会查询操作系统缓存
+- 本地DNS服务器:如果操作系统缓存中也没有,操作系统会查询配置的本地DNS服务器(通常是ISP提供的)
+- 递归查询:本地DNS服务器如果没有缓存,会进行递归查询,从根DNS 服务器开始,逐级查询顶级域名服务器、权威DNS服务器,直到找到对应的IP地址
+3. 建议TCP链接:TCP三次握手
+- SYN:浏览器发送一个 SYN 包到服务器,表示请求建立连接
+- SYN-ACK:服务器收到 SYN 包后,返回一个 SYN-ACK 包,表示同意连接
+- ACK:浏览器收到 SYN-ACK 包后,发送一个 ACK 包,表示连接建立成功
+4. SSL/TLS四次握手(只有https才有这一步)
+5. 浏览器发送HTTP/HTTPS请求
+- 建立TCP连接后,浏览器发送HTTP或HTTPS请求到服务器。对于HTTPS,还包括建立TLS/SSL加密连接的步骤:
+- ClientHello:客户端发送 ClientHello 消息,包含支持的加密算法等信息。
+- ServerHello:服务器响应 ServerHello 消息,选择加密算法,并发送服务器证书。
+- 证书验证:浏览器验证服务器证书的有效性。
+- 密钥交换:客户端和服务器协商对称密钥,用于后续加密通信。
+- 握手完成:双方确认加密参数,开始加密通信。
+6. 服务器响应请求并返回数据
+- 路由处理:根据请求路径,确定处理逻辑。
+- 数据库查询:如有需要,查询数据库获取数据。
+- 逻辑处理:根据业务逻辑生成响应内容。
+- 返回响应:服务器生成响应头和响应体,并发送回浏览器。
+7. 浏览器接受响应并解析
+- 解析HTTP响应头:获取状态码、内容类型、缓存控制等信息。
+- 解析HTML:将HTML文本解析为DOM树。
+- 解析CSS:将CSS文本解析为CSSOM树,并应用到DOM树中。
+- 解析JavaScript:解析并执行JavaScript代码,可能会操作DOM树和CSSOM树。
+- 解析图片、字体等资源:根据HTML和CSS内容,发送请求加载外部资源。
+8. 页面渲染
+浏览器将DOM树和CSSOM树结合起来,构建渲染树。渲染树包含了所有需要显示的节点及其样式信息
+
+## DNS解析
+DNS解析是将人类容易记忆的域名(如www.example.com)转换为计算机可识别的IP(如192.0.2.1)地址。
+
+DNS-prefetch(DNS预获取)是尝试在请求资源之前解析域名。这可能是后面要加载的文件,也可能是用户尝试打开的链接目标。域名解析和内容载入是串行的网络操作,所以这个方式能减少用户的等待时间,提升用户体验。
+
+dns-prefetch 可帮助开发人员掩盖 DNS 解析延迟。 HTML的``元素通过dns-prefetch的rel属性值提供此功能
+```html
+
+```
+注意:
+1. dns-prefetch仅对**跨域**域上的DNS查找有效,因此避免使用它来指向您的站点或域。这是因为,到浏览器看到提示时,您站点域背后的IP已经被解析
+2. dns-prefetch需慎用,多页面重复DNS预解析会增加重复DNS查询次数
+3. 默认情况下浏览器会对页面中和当前域名(正在浏览网页的域名)不在同一个域的域名进行预获取,并且缓存结果,这就是隐式的 DNS Prefetch。如果想对页面中没有出现的域进行预获取,那么就要使用显示 DNS Prefetch 了。
+
+**更多DNS解析优化**
+1. 延长DNS缓存时间
+2. 尽可能使用A或AAAA记录代替CNAME
+3. 使用CDN加速域名
+4. 自己搭建DNS服务
+
+**清除DNS缓存**
+1. 清除浏览器DNS缓存
+- 清除DNS缓存:chrome://net-internals/#dns
+- 有时候也需同时清除套接字缓存池:chrome://net-internals/#sockets
+
+2. 清除系统DNS缓存
+```js
+// 在windows中查看DNS缓存记录
+ipconfig /displaydns
+
+// 在windows中清除DNS缓存记录
+ipconfig /flushdns
+
+// 在macOS中清除DNS缓存记录
+sudo killall -HUP mDNSResponder
+```
+
+## HTTP长连接
+### 短连接
+HTTP协议的初始版本中,每进行一次HTTP通信就要断开一次TCP连接。每次的请求都会造成无谓的TCP连接建立和断开,增加通信的开销。
+
+为了解决这个问题,有些浏览器在请求时,用了一个非标准的Connection字段
+```HTTP
+Connection: keep-alive
+```
+这个字段要求服务器不要关闭TCP连接,以便其他请求复用。服务器同样回应这个字段。
+```HTTP
+Connection: keep-alive
+```
+一个可复用的TCP连接就建立了,直到客户端或服务器主动关闭连接。但是,这不是标准字段,不同实现的行为可能不一致,因此不是根本的解决办法。
+
+### 长连接
+1997年1月,HTTP/1.1版本发布,只比1.0版本晚了半年。它进一步完善了HTTP协议,直到现在还是最流行的版本。
+HTTP 1.1 版的最大变化,就是引入了持久连接(HTTP Persistent Connections),即TCP连接默认不关闭,可以被多个请求复用,不用声明Connection: keep-alive。
+持久连接的好处在于减少了TCP连接的重复建立和断开所造成的额外开销,减轻了服务器端的负载。另外,减少开销的那部分时间,使HTTP请求和响应能够更早的结束,这样Web页面的显示速度也就相应提高了。
+客户端和服务器发现对方一段时间没有活动,就可以主动关闭连接。不过,规范的做法是,客户端在最后一个请求时,发送Connection: close,明确要求服务器关闭TCP连接。
+目前,对于同一个域名,大多浏览器允许同时建立6个持久连接。
+
+## HTTP2
+HTTP/1.1版的头信息肯定是文本(SACII编码),数据体可以是文本,也可以是二进制。HTTP2/则是一个彻底的二进制协议,头信息和数据体都是二进制,并且统称为“帧”:头信息帧和数据帧。
+HTTP/2是对HTTP/1.x的改进,旨在提高性能、减少延迟,并提供更高效的传输机制。
+1. 多工
+HTTP/2复用TCP连接,**在一个连接里,客户端和浏览器都可以同时发送多个请求或回应,而且不用按照顺序一一对应**,这样就避免了“队头堵塞”。
+举例来说,在一个TCP连接里面,服务器同时收到了A请求和B请求,于是先回应A请求,结果发现处理过程非常耗时,于是就发送A请求已经处理好的部分, 接着回应B请求,完成后,再发送A请求剩下的部分。
+这样双向的、实时的通信,就叫做多工。
+2. 数据流
+因为HTTP/2的数据包是不按顺序发送的,同一个连接里面连续的数据包,可能属于不同的回应。因此,必须要对数据包做标记,指出它属于哪个回应。
+HTTP/2将每个请求或回应的所有数据包,称为一个数据流(stream)。每个数据流都有一个独一无二的编号。数据包发送的时候,都必须标记数据流ID,用来区分它属于哪个数据流。另外还规定,客户端发出的数据流,ID一律为奇数,服务器发出的,ID为偶数。
+数据流发送到一半的时候,客户端和服务器都可以发送信号(RST_STREAM帧),取消这个数据流。1.1版取消数据流的唯一方法,就是关闭TCP连接。这就是说,HTTP/2可以取消某一次请求,同时保证TCP连接还打开着,可以被其他请求使用。
+客户端还可以指定数据流的优先级。优先级越高,服务器就会越早回应。
+3. 头信息压缩
+HTTP 协议不带有状态,每次请求都必须附上所有信息。所以,请求的很多字段都是重复的,比如Cookie和 User Agent,一模一样的内容,每次请求都必须附带,这会浪费很多带宽,也影响速度。
+HTTP/2对这一点做了优化,引入了头信息压缩机制(header compression)。一方面,头信息使用gzip 或compress压缩后再发送;另一方面,客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了。
+4. 服务器推送
+HTTP/2允许服务器未经请求,主动向客户端发送资源,这叫做服务器推送(server push)。
+常见场景是客户端请求一个网页,这个网页里面包含很多静态资源。正常情况下,客户端必须收到网页后,解析HTML源码,发现有静态资源,再发出静态资源请求。其实,服务器可以预期到客户端请求网页后,很可能会再请求静态资源,所以就主动把这些静态资源随着网页一起发给客户端了。