这是最近抽空听的kkb的《前端性能优化》的大课,整体来说,内容比较散,而且枯燥性的概念比较多,但是还是有一些启发和新知识的获取,在此作为个人的笔记记录一下。
从输入url到页面显示发生了什么?
1、DNS
即域名解析,将域名转换为IP地址,浏览器的查询过程本质上还是缓存优先(快):
浏览器缓存:浏览器会按照一定的频率缓存 DNS 记录。
操作系统缓存:如果浏览器缓存中找不到需要的 DNS 记录,那就去操作系统(host文件)中找。
路由缓存:路由器也有 DNS 缓存。
ISP 的 DNS 服务器:ISP 是互联网服务提供商(Internet Service Provider)的简称,ISP 有专门的 DNS 服务器应对 DNS 查询请求。
根服务器:ISP 的 DNS 服务器还找不到的话,它就会向根服务器发出请求,进行递归查询(DNS 服务器先问根域名服务器.com 域名服务器的 IP 地址,然后再问.baidu 域名服务器,依次类推)。
稍微深入了解DNS,可以参阅一篇比较有意思的文章:美国如果把根域名服务器封了,中国会从网络上消失?
2、建立TCP连接
三次握手,慢启动,滑动窗口,超时重画等TCP相关的概念要掌握
处理大数据场景,TCP带来的一些启发:
- 分片(太大)
- 慢启动(让网络包的大小逐渐匹配网速)
3、发送HTTP请求
掌握缓存,etag,expire,理解强缓存、协商缓存
TCP 三次握手结束后,开始发送 HTTP 请求报文。
请求报文由请求行(request line)、请求头(header)、请求体三个部分组成,如下图所示:
4、服务器处理请求并返回 HTTP 报文
- SPA,后端丢一个空的html,然后加载js,css,js执行完成之后里面有Vue/React等,剩下是框架执行的逻辑:框架解析路由,设置应用主题等(缺点:首屏慢)
- SSR 首屏渲染出来就有完整DOM结构提升首屏渲染速度,利于SEO,eg. nuxt,next)
5、浏览器渲染
- 根据 HTML 解析出 DOM 树
- 根据 CSS 解析生成 CSS 规则树
- 结合 DOM 树和 CSS 规则树,生成渲染树
- 根据渲染树计算每一个节点的信息
- 根据计算好的信息绘制页面
掌握重绘、回流
TCP与UDP常见协议
| TCP | UDP |
|---|---|
| HTTP,FTP,SSH | DNS |
全流程优化概述
蓝色(网络层):主要是利用缓存来优化
- 对于DNS来说,成熟的解决方案就是dns-prefetch
- 对于TCP来说,做好DNS预解析、做好缓存的设立
红色(响应层面):
一些指标TTI(Time to Interactive)
紫色(响应之后):
SPA和SSR,重绘、回流
图片的优化
图片的优化一般对整体的收益比较高。
1、格式问题:jpg,png,webp等
2、node里压缩图片等,其实CDN最合适的方式就是通过url来定制图片格式、大小
spa的首屏和seo问题的解决
- 预渲染 prerender
- 静态化
- 同构(ssr+spa的综合体)
performance
Performance 接口可以获取到当前页面中与性能相关的信息,具体参阅下图:
这些可以算出来的指标都是硬性的(比如DNS花费的时间),和交互相关的,需要别的方式来统计(比如FMP),MutationObserver接口提供了监视对DOM树所做更改的能力。
缓存
性能指标
- FP(First Paint)
- FCP(First Content Paint)
- FMP(First Meaningful Paint)
- TTI(Time to Interactive)
FMP的计算
1、固定好dom的id,统计高度变化时间(和业务强绑定)
2、统计首屏dom的面积,计算占比
3、dom变化趋势
计算demo:
由于所有html出来之后,没法知道谁是最重要的节点
1、页面进入 使用mutationObserver来监听DOM变化
2、对变化DOM打上标记
3、文档的load事件触发
4、遍历DOM tree
5、根据元素的可视区域,计算元素的权重
6、递归遍历父元素,对比合并(有的合并有的不合并)
7、get一下权重最高的
8、判断是否加载完毕
8.1.是不是img video audioe这种资源标签,资源加载事件
performance.getEntries
8.2.只是单纯的DOM,时间-dom变化
9、算出FMP
简单粗暴计算:
mutationObserver首屏load出来80%(举例)就算
框架层面(框架本身)的性能优化
1、Vue1响应式
2、React15 dom diff
3、Vue1和React15在数据量大的时候都会有卡顿问题**(60fps 16.6ms) **
4、Vue2 组件级响应式,组件内部dom diff
5、React16 fiber tree, 时间切片计算
6、Vue3(treeshaking)
proxy做响应式
静态标记: 做到了按需更新(不需要时间切片)
Vue2的静态标记做的很简单,只有整个根元素下纯静态的标记会做,如果静态标记在
v-if v-for下面做不了;如果一个节点只有一个属性是动态的,Vue中会diff所有属性,
Vue3中只会diff这一个动态属性。
参考
HOW BROWSER WORKS
经典面试题:从 URL 输入到页面展现到底发生什么?
(详解)从浏览器输入 URL 到页面展示过程发生了什么?