性能优化-输入URL到页面展示发生了什么

12/2/2021 3183 阅读需要16分钟
0
0
AI总结
性能优化是提升网页加载速度和用户体验的关键。网页加载时间超过3秒会导致57%的用户关闭页面,直接影响交易量和下单率。浏览器从单进程演变为多进程架构,包括浏览器主进程、GPU进程、网络进程、渲染进程和插件进程,提升了稳定性、流畅性和安全性。 从URL输入到页面加载,浏览器经历了域名解析、建立TCP连接、读取缓存、发起请求、解析HTML、构建DOM树、样式计算、布局、分层、绘制、栅格化、合成和显示等步骤。渲染流程包括构建DOM树、样式计算、布局、分层、绘制、栅格化和合成,最终生成页面并显示。 优化性能可以从代码层面、工程化、API缓存方案和规范化等方面入手。理解重绘和重排、虚拟DOM的作用以及每一帧的渲染过程,有助于进一步优化性能。

性能优化1

一.为什么要优化性能

1.网页加载时间超过3秒就会有百分之57的用户会选择关闭当前网页; 2.在ToC的业务中糟糕的性能直接影响到交易量,下单率等等;

曾经我们的在学习前端的时候相信都接触过雅虎军规35条等等的性能优化建议

二.我们如何看到网页的

2.1 进程和线程

进程包含线程,线程依赖进程。曾经的浏览器是单进程的。 png 如此多的功能模块运行在一个进程里,是导致单进程浏览器不稳定不流畅不安全的一个主要因素。下面我就来一一分析下出现这些问题的原因。

2007年以后多进程浏览器的开始盛行;Chrome的改进了浏览器的设计。 如下:

png

如今演变成现在的这样子:

png

从图中可以看出,最新的 Chrome 浏览器包括:1 个浏览器(Browser)主进程、1 个 GPU 进程、1 个网络(NetWork)进程、多个渲染进程和多个插件进程。

浏览器进程:负责交互,显示,提供存储等功能;

渲染进程:核心任务是将 HTML、CSS 和 JavaScript 转换为用户可以与之交互的网页,排版引擎 Blink 和 JavaScript 引擎 V8 都是运行在该进程中,默认情况下,Chrome 会为每个 Tab 标签创建一个渲染进程。出于安全考虑,渲染进程都是运行在沙箱模式下;

GPU进程:处理3D css;

网络进程:负责网络的资源的加载工作;

插件进程:·····

三.老生常谈-从url输入到页面加载出来经历了什么

1.浏览器进程,输入URL会开始域名解析,先去本地host去匹配,如果发现host中存在映射关系,就直接去对应的ip,如果没有就要经过dns解析,查找ip;

dns解析过程如下: 浏览器: 域名 -> 浏览器缓存 -> Y -> ip 浏览器没有就会到本机: -> OS DNS缓存/hosts -> Y -> 返回ip 没有就到路由器: -> dns缓存中是否有 -> Y ->返回 没有 DNS服务器: -> dns服务器 // 如果没有命中还会去到顶级域名服务器查找 2.获取端口号,http默认为80 https默认为443 3.网络进程,根据ip和端口号建立tcp链接,经历3次握手如果是https还要建立tls链接;

相关建立链接的过程自行查找,可以查看一下http0.9,1.0,1.1,2.0,3.0的区别 4.发起请求前会读取本地的缓存;

首先会读取内存中的,再是硬盘,如果都没有再去服务端; 在network中会看到from memory cache,from disk cache, 304的状态码; 5.http发起请求先检查浏览器的强缓存,如果命中,直接返回对应资源文件的副本;

强缓存通过响应头字段控制:Expires,cache-control,expires是过期时间,是一个绝对值,过期就重新请求; cache-control有几个属性值,比如max-age,no-cache,no-store等

cache-control优先级高于expires

6.如果没有命中,就需要走协商缓存会去对比资源,是否需要更新,如果不需要读取本地的缓存,如果需要更新就加载新的资源; 7.服务器返回HTML响应给浏览器 8.渲染进程:浏览器解析HTML 9.对HTML页面引用的所有资源包括js,css,图片等等,浏览器都发送GET请求,又重复上面的过程

以上是表面上的经历,在浏览器环境中又做了些什么呢? 1.首先,浏览器进程接收到用户输入的 URL 请求,浏览器进程便将该 URL 转发给网络进程。 2.然后,在网络进程中发起真正的 URL 请求。接着网络进程接收到了响应头数据,便解析响应头数据,并将数据转发给浏览器进程。浏览器进程接收到网络进程的响应头数据之后,发送“提交导航 (CommitNavigation)”消息到渲染进程;渲染进程接收到“提交导航”的消息之后,便开始准备接收 HTML 数据,接收数据的方式是直接和网络进程建立数据管道; 3.最后渲染进程会向浏览器进程“确认提交”,这是告诉浏览器进程:“已经准备好接受和解析页面数据了”。 4.浏览器进程接收到渲染进程“提交文档”的消息之后,便开始移除之前旧的文档,然后更新浏览器进程中的页面状态

简单来说就是:url输入 -> 网络进程 -> 浏览器进程 -> 遇到html -> 提交导航 -> beforeunload -> 导航完成 -> 渲染进程开始准备

4.渲染流程是怎么样的

渲染流程非常的复杂,但是可以分步来看,总体流程大概如下:

HTML/CSS/JS -> 子流程 -> 子流程 -> 子流程 -> 完整的页面。

子流程包含以下内容:构建 DOM 树、样式计算、布局阶段、分层、绘制、分块、光栅化和合成。

如何去分析这个过程;关注三要素:输入-> 加工 -> 输出。

4.1 构建DOM树

问1: 为何要构建DOM树 ?

问2: 如何构建DOM树 ?

输入HTML -> 解析HTML -> DOM树

问3: 如何解析?

1.首先浏览器会将原始字节的按照编码格式转成字符串 2.第二部 令牌化;将字符串转成成HTML,标签; 3.给这些标签转化成一个个对象,赋予样式和属性; 4.生成DOM树

png

4.2 样式计算

目的:计算DOM节点的样式;

如何计算?

第一步:渲染进程在接收到css文件的时候,需要该文件进行转化,转化成浏览器能够认识的样式表(stylesheets)

第二步:标准化属性,例如em,rem => px等;

第三步:计算每个DOM节点的样式;

1.先继承样式 2.再根据样式的优先级来;

总体来说和DOM差不多;

4.3 布局(LayOut)

DOM树和节点的样式已经有了,下一步该做什么呢?

1.创建布局树(LayOut tree)

创建过程分两步: 1.遍历 DOM 树中的所有可见节点,并把这些节点加到布局树中; 2.而不可见的节点会被布局树忽略掉

2.计算位置

总结:在 HTML 页面内容被提交给渲染引擎之后,渲染引擎首先将 HTML 解析为浏览器可以理解的 DOM;然后根据 CSS 样式表,计算出 DOM 树所有节点的样式;接着又计算每个元素的几何坐标位置,并将这些信息保存在布局树中。

4.4 分层

我们知道页面是二维的,但是有些属性会导致页面出现层级的情况,比如z-index; 这时候浏览器会对我们的DOm节点进行分图层,设计同学应该知道。一个页面是有多个图层堆叠起来的; 此时此刻会生成一颗 图层树(Layer Tree)

png

1.优先级如下: 正z-index > z-index = 0 > inline > float > block > 负z-index > border > background

2.初次以为需要裁剪的地方也会单独占有一个层;

这里所说的裁剪并非是canavs的裁剪,而是绘制页面中的裁剪

4.5 绘制(paint)

绘制图层,绘制过程会生成绘制列表,然后commit到渲染进程,由渲染进程中的合成线程完成绘制;

4.6 栅格化

合成线程会把图层分为256x256或者是 512x512的图块;合成线程会按照视口附近的图块来优先生成位图,实际生成位图的操作是由栅格化来执行的。所谓栅格化,是指将图块转换为位图。

4.7 合成和显示

一旦所有图块都被栅格化,合成线程就会生成一个绘制图块的命令——“DrawQuad”,然后将该命令提交给浏览器进程。这时候浏览器进程接收到命令后就会将页面内容提交到内存中;最后显示在页面上。

总结大概是这样:

1.渲染进程将 HTML 内容转换为能够读懂的 DOM 树结构。 2.渲染引擎将 CSS 样式表转化为浏览器可以理解的 styleSheets,计算并生成 CSSOM 树。 3.创建布局树,并计算元素的布局信息。 4.对布局树进行分层,并生成图层树。 5.为每个图层生成绘制列表,并将其提交到合成线程。 6.合成线程将图层分成图块,并在光栅化线程池中将图块转换成位图。 7.合成线程发送绘制图块命令 DrawQuad 给浏览器进程。 8.浏览器进程根据 DrawQuad 消息生成页面,并显示到显示器上。

大总结

1.浏览器进程,输入URL会开始域名解析,先去本地host去匹配,如果发现host中存在映射关系,就直接去对应的ip,如果没有就要经过dns解析,查找ip;

dns解析过程如下: 域名 -> hosts命中 -> 返回ip 域名 -> dns缓存中是否有 -> Y ->返回 域名 -> dns缓存中是否有 -> dns服务器 // 如果没有命中还会去到顶级域名服务器查找 2.获取端口号,http默认为80 https默认为443 3.网络进程,根据ip和端口号建立tcp链接,经历3次握手如果是https还要建立tls链接;

相关建立链接的过程自行查找,可以查看一下http0.9,1.0,1.1,2.0,3.0的区别 4.发起请求前会读取本地的缓存;

首先会读取内存中的,再是硬盘,如果都没有再去服务端; 在network中会看到from memory cache,from disk cache, 304的状态码; 5.http发起请求先检查浏览器的强缓存,如果命中,直接返回对应资源文件的副本;

强缓存通过响应头字段控制:Expires,cache-control,expires是过期时间,是一个绝对值,过期就重新请求; cache-control有几个属性值,比如max-age,no-cache,no-store等

cache-control优先级高于expires

6.如果没有命中,就需要走协商缓存会去对比资源,是否需要更新,如果不需要读取本地的缓存,如果需要更新就加载新的资源; 7.服务器返回HTML响应给浏览器 8.渲染进程:浏览器解析HTML 9.对HTML页面引用的所有资源包括js,css,图片等等,浏览器都发送GET请求,又重复上面的过程

以上是表面上的经历,在浏览器环境中又做了些什么呢? 1.首先,浏览器进程接收到用户输入的 URL 请求,浏览器进程便将该 URL 转发给网络进程。 2.然后,在网络进程中发起真正的 URL 请求。接着网络进程接收到了响应头数据,便解析响应头数据,并将数据转发给浏览器进程。浏览器进程接收到网络进程的响应头数据之后,发送“提交导航 (CommitNavigation)”消息到渲染进程;渲染进程接收到“提交导航”的消息之后,便开始准备接收 HTML 数据,接收数据的方式是直接和网络进程建立数据管道; 3.最后渲染进程会向浏览器进程“确认提交”,这是告诉浏览器进程:“已经准备好接受和解析页面数据了”。 4.浏览器进程接收到渲染进程“提交文档”的消息之后,便开始移除之前旧的文档,然后更新浏览器进程中的页面状态

简单来说就是:url输入 -> 网络进程 -> 浏览器进程 -> 遇到html -> 提交导航 -> beforeunload -> 导航完成 -> 渲染进程开始准备 10.构建DOM树 11.构建CSSOM 12.生成渲布局树 13.分层 14.绘制 15.栅格化 16.合成 17.存入内存 18.展示页面

思考

1.什么是重绘和重排? 2.每个阶段如何优化? 3.为什么需要虚拟DOM? 4.微观视角下的浏览器-每一帧的过程? ...

后续规划

1.代码层面 2.工程化,代码分割,按需加载 3.API缓存方案 4.规范化 ...