什么是前端性能
它是一个跨功能需求,优化的方式有很多种,可以将其总结分为俩大类,第一类是运行环境的优化,如【网络、服务器资源】等,第二类为代码级别的优化,例如js中DOM操作优化,css选择器优化,图片优化以及HTML结构优化等等。
理解影响性能的关键因素
延迟
带宽(流量、流量控制)
DNS解析
TCP/TLS(安全传输层协议)
静态资源
常用的优化策略
延迟
传输延迟
cdn
缓存
与服务器的物理距离越近,延迟越低
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eZvd4YHa-1615344692384)(C:\Users\JCM-PC\AppData\Roaming\Typora\typora-user-images\image-20210308094641392.png)]]
**缓存 **
- 缓存当然是最快的,比任何服务器/CDN多块
- 通过Cache-Control HTTP标头合理制定缓存
- Cache
- 真正的静态元素也许可以被设置为永远可用
- 使用hash tag
- Etag也是有性能消耗的
- 后面有重点提到缓存
带宽
js延迟 按需加载
//解决多次点击多次加载问题
let obj = {};
//按需加载js
function dynamicLoadJS(url, callback) {
//开关
if (obj[url]) {
callback();
return;
}
obj[url] = true;
var head = document.getElementsByTagName("head")[0];
var script = document.createElement("script");
script.type = "text/javascript";
script.src = url;
if (typeof callback === "function") {
script.onload = script.onreadystatechange = function () {
if (
!this.readyState ||
this.readyState === "loaded" ||
this.readyState === "complete"
) {
callback();
script.onload = script.onreadystatechange = null;
}
};
}
head.appendChild(script);
}
每次加载资源后,需要缓存,防止重复多次加载
图片按需加载(懒加载)
// 获取元素是否在可视区域
function isElementInViewport(el) {
var rect = el.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <=
(window.innerHeight || document.documentElement.clientHeight) &&
rect.right <= (window.innerWidth || documentElement.clientWidth)
);
}
function checkImg() {
let imgs = document.querySelectorAll("img[lazy]");
Array.from(imgs).forEach((ele) => {
if (isElementInViewport(ele)) {
loadImg(ele);
}
});
}
function loadImg(el) {
if (!el.src) {
let source = el.dataset.src;
el.src = source;
}
}
<img data-src="cdn.png" alt="" lazy />
按需加载css
const link = document.createElement('link');
link.rel = 'stylesheet'
link.href = './css/style.css';
document.head.appendChild(link);
资源预加载(preload 和iframe)
提前加载资源
//h5支持
<link rel="preload" as="font" href="http://at.......">
<link rel="preload" as="script" href="http://at.......">
<link rel="preload" as="script" href="http://at.......">
预加载css
<link rel="preload" href="./css/style.css" as="style">
preload是告诉浏览器页面必定需要的资源,浏览器一定会加载这些资源;
preload是确定会加载指定资源,如在我们的场景中,x-report.js初始化后一定会加载PcCommon.js和TabsPc.js,则可以预先preload这些资源。
prefetch是告诉浏览器页面可能需要的资源,浏览器不一定会加载这些资源。
prefetch是预测会加载指定资源,如在我们的场景中,我们在页面加载后会初始化首屏组件,当用户滚动页面时,会拉取第二屏的组件,若能预测用户行为,则可以prefetch下一屏的组件。
DNS解析
### DNS解析流程
- 查找浏览器缓存
- 查找系统缓存
- 查找路由器缓存
- 查找ISP DNS缓存(运营商)
- 迭代查询
优化思路
- 减少DNS查找,避免重定向
- 使用浏览器DNS缓存、计算机DNS缓存、服务器DNS缓存,防止DNS迭代查询;
- 使用keep-alive特性来减少DNS查找的频率(服务端)
- 使用较少的域名(服务器主机)来减少DNS查找的数量(控制不了)
影响DNS缓存的因素
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gwQO98sU-1615344692398)(C:\Users\JCM-PC\AppData\Roaming\Typora\typora-user-images\image-20210308152114896.png)]]
DNS预解析
可以通过用meta信息来告知浏览器,我这页面要做的DNS预解析
<meta http-equiv="x-dns-prefetch-control" content="on" />
可以使用link标签来强制对DNS做预解析
<link rel="dns-prefetch" href="http://ke.qq.com" />
TCP/TLS
- 减少页面的重定向向页面重定向性能消耗较大
- 减少Rewrite(跨域)
- SPA(单页面)减少tcp请求
- cdn:更低的延迟
- http2.0
http2.0优点
-
二进制分帧
-
首部压缩
-
多路复用
同一个域名下,可以同时请求很多
-
请求优先级
-
服务器推送
不用发请求,服务端直接推送
-
更安全(https支持)
-
流量控制
http1.x的主要缺点
- http1.0一次只允许在一个TCP连接发起一个请求,HTTP/1.1使用流水线技术也只能处理部分请求并发,任然存在堵塞队列的问题,因此客户端需要发送多次请求时,通常会采用建立多连接来减少延迟。
- 单向请求,只能有客户端发起
- 请求报文与响应报文首部信息冗余
- 数据未压缩,导致数据的传输量大。
静态资源
- 数据压缩传输(gzip,broti,http2.0)
- webpack:tree shaking,。。。
- 移除不必要的lib引用,或迁移到CND(webpack-bundle-analyzer)
PageSpeed Insights使用
Profile panel(memory)
-
Comstructor(构造函数)表示所有通过该构造函数生成的对象
-
Distance 对象到达GC根的最短距离
-
Objects Count 对象的实例数
-
Shallow size 对于的构造函数生产的对象的shallow sizes(直接占有内存)总数
-
Retained size 展示了对应对象所占用的最大内存
-
TTFB-首字节时间,是指从客户端开始和服务端交互到服务端开始向客户端浏览器传输数据的时间
TTFB优化的方法有:
- 减少DNS查询
- 使用CND
chrome关键性能指标
TTFB(time to First Byte)
最初的网络请求被发起到服务器接收第一个字节这段时间,它包含了Tcp连接时间,发送HTTP请求时间和获取响应的第一个字节的时间
注意:网页重定向越多,TTFB越高
HTTP优化的方法:
- 减少DNS查询
- 使用CDN
- 提早输出(flush服务端提早返回数据)
TTSR(Time To Start Render)
开始渲染时间,指某些非空元素开始在浏览器显示的时间,这也是一项重要的指标,即TTSR越短,用户看到页面越快。
TTSR优化:
- 优化TTSB
- 降低客户端cpu消耗,即页面加载初期不要有大脚本运行,把js脚本放到页面下方
。。。。。。。。
脚本 window.performance
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-djMR5zuh-1615344692404)(C:\Users\JCM-PC\AppData\Roaming\Typora\typora-user-images\image-20210308175530498.png)]]
重定向耗时 = redirectEnd - redirectStart;
DNS查询耗时 = domainLookupEnd - domainLookupStart;
TCP连接耗时 = connectEnd - connectStart;
HTTP请求耗时 = responseEnd - responseStart;
解析dom耗时 = domComplete - domInteractive;
白屏时间 = responseStart - navigationStart;
DOMready时间 = domContentLoadedEventEnd - navigationStart;
onload时间 = loadEventEnd - navogationStart;
首屏加载
使用prerender-spa-plugin 渲染首屏 (骨架屏)
缓存(服务端)
出发点:拿空间换时间
强缓存
Expires
Expires是http1.0的规范
Cache-Control
Cache-Control是在http1.1中出现的
- no-cache: 不使用本地缓存,需要使用缓存协商,先与服务器确认返回的响应是否被更改,如果之前的响应中存在ETag,那么请求的时候会与服务端验证,如果资源未被更改,则可以避免重新下载。
- no-store:直接禁止浏览器缓存数据,每次用户请求该资源,都会向服务器发送一些请求,每次都会下载完整的资源
- public:可以被所有用户缓存,包括终端用户和CDN等中间代理服务器
- private:只能被终端用户的浏览器缓存,不允许CDN等中继缓存服务器对其缓存。
- Cache-Control与Expirse可以在服务端配置同时启用,同时启用的时候Cache-Control优先级高
协商缓存
Service Worker
作为一个比较新的技术,我们可以把server Worker理解为一个介于客户端和服务端之间的一个代理服务器。在Service Worker中我们可以做很多事情,比如拦截客户端的请求/向客户端发送消息,向服务端发送请求等等,其中最重要的是离线资源缓存。
优点:所有的资源都可以缓存
缺点:缓存的资源必须是同域,需要是https的方式访问
HTML5 manifest 离线缓存技术
web Worker
应用场景:前端需要大数据量的计算
怎么用(主线程和后端线程的通信):postmessage发送数据,
接收:this.addEventlistener(‘message’,()=>{})
vue项目中中的性能优化
-
静态资源压缩传输
-
资源懒加载,预加载(css,组件,图片。。。)
const Hotshowing = ()=>import('./src/awd/sda.vue')
-
v-if和v-show的选择调用
-
减少watch的使用,慎用deep watch
-
ssr(服务端渲染)根据业务需求
-
骨架屏(通过占位线框元素,渐进式加载数据)
-
keep-alive缓存