性能优化
回到那到面试题
- 输入
- URL:资源定位符js
// http:www.pipi.com - http协议 // 面试: http & TCP - (TCP/IP) => 计算机网络 // 1. http - 应用层 <=> TCP - 传输层 // 2. 关联:http基于TCP实现的连接 => 追问:TCP的连接特性(请求、发送、断开)=> debug过程中,连接挂了 // http 1.0 => 1.1 => keep-alive - 保持TCP的连接状态(不用反复的建立连接) // http 1.1 => 2.0 => 多条并发复用同一条通路 - 避免chrome(连接上限6)TCP连接限制 - 复用通路,无并发限制 // => UDP vs TCP 的区别 // 3.状态:http - 无状态 <=> TCP - 有状态 // 优化点: // => socket连接,并不是连接,而是一个封装化的TCP,方便使用和调用 // https:www.pipi.com - https协议 // 追问:https & http // 1. https = http + ssl => 位于TCP与传输应用协议之间 // 2. 实现原理 // 3. HTTPS多次连接:导致网络请求加载时间延长:增加开销和消耗 // 优化上述3 方案1:=> 合并请求 + 长连接 => 二维码已过期 // 方案2:=> 中间层 整合请求 => 异常处理
- 域名解析
js
// 1.浏览器解析 - 浏览器中会缓存DNS
// 2.系统缓存 - 操作系统会在系统中做一些缓存 => 改host
// 3.路由器缓存 - 各级路由器上
// 4.运营商的各级缓存 => traceRoute
// 5.根域名服务器
// 优化:
// CDN - Content Delivery Network
// 1. 为同一个主机配置多个ip地址
// 2. 就近就快匹配
// 3. LB - 负载均衡
// 缓存 => 各级缓存 => CDN => 浏览器
- web服务器
js
// apache、nginx
// 1. 接受请求 => 传递给服务端的代码
// 2. 通过反向代理 => 传递给其他的服务器
// 3. 不同的域名 => 指向相同的ip的服务器 => 引导到不同的服务监听端口
// nginx => 跨域头
前端网络优化
- 手写并发控制 - QPS - limit
js
// 面试:并发优化 10个请求,由于后台性能所限或者业务需求
// 分析:
// 输入:max
// 存储:taskQue
// 内容:执行 - run | 创建任务 - createTask
// 唯一性 => 单例模式
class LimitPromise {
constructor(max) {
// 异步任务并发上限
this._max = max || 6;
// 当前正在执行任务的数量
this._count = 0;
// 等待执行的任务队列
this._taskQueue = [];
// 单例模式复用
this.instance = null;
}
run(caller) {
// 主入口
// 输入:外部要传入添加的请求
// 输出:返回队列处理的promise
return new Promise((resolve, reject) => {
// 创建一个处理任务
const task = this._createTask(caller, resolve, reject);
// 当前队列任务数量是否达到上限
if (this._count >= this._max) {
this._taskQueue.push(task);
} else {
task();
}
})
}
_createTask(caller, resolve, reject) {
return () => {
caller().then(res => {
resolve(res);
}).catch(err => {
reject(err)
}).finally(() => {
this._count--;
if (this._taskQueue.length) {
// 完成任务清出
const task = this._taskQueue.shift();
task();
}
})
this._count++;
}
}
// 单例
static getInstance(max) {
if (!this.instance) {
this.instance = new LimitPromise(max);
}
return this.instance;
}
}
浏览器在渲染时
浏览器的执行顺序
主线: HTML => DOM + CSSOM => renderTree + js => layout => paint
面试:
repaint - 改变文本、颜色改变
reflow - 元素个数、几何尺寸变化
=> 优化点:减少repaint、避免reflow
=> display:none => reflow; visibility:hidden => repaint;
不如opacity
脚本执行层面
mark & sweep => 触达标记,锁定清空、未触达的直接抹除
js
const pipi = {
js:{
performance: "good",
teacher:"云隐"
}
}
// 建立引用关系
const _obj = pipi;
// 引用源替换 - 暂未gc - 因为_obj还在调用
pipi = "best";
// 深入层级做引用 - 暂未gc
const _class = _obj.js;
// 引用方替换 - 暂未gc
_obj = "over";
// 但是可以强制gc
_class = null;
// 内存泄漏 - 避免莫名奇妙的全局变量
function foo(){
bar1 = "";
this.bar2 = "";
}
// 未清理的定时器
setInterval(()=>{
},1000)
// 使用后的闭包 - 及时清理
function pipi(){
const _no = 1;
return { number: _no }
}
项目优化
首页秒开:
- 懒加载 - 路由、图片、数据
- 数据:首屏的viewport
- 图片,压缩
- 减少回流和重排
- CDN加速
- gzip加速
缓存:静态资源
- 不变的,强制缓存:cache-controll:max-age
- 变化快的,协商缓存:etag
离线化:线上的数据 -> 静态到本地 配置 prerender-spa-plugin vue.config.js中plugins引入new PreenderSpaPlugin
白屏和卡顿:
- 懒加载和图片处理
- DNS
<meta http-equiv='x-dns-prefetch-control'>
预解析
卡顿:
- 用队列的思想,把复杂的功能拆分为细小的功能
其他优化:
- 压缩css js html
- 才用cdn加速
- loader用include减少路径查询
- treeshaking