重学前端 浏览器是如何工作的
前端 浏览器是如何工作的
URL
显示网页得内容
1、浏览器通过HTTP
或者 HTTPS
协议请求代码资源
2、将请求回来得HTML
代码经过解析,构建dom
树
3、解析dom
树css
4、最后根据CSS
属性怼元素逐个进行渲染,得到内存中得位图
5、一个可选得步骤是对位图进行合成,这会极大得增加后续绘制得速度
6、合成之后,在绘制到界面上
流程: http
>构建dom树
>计算css
>排版
>渲染和合成
==>绘制
【注】:从HTTP请求回来,就产生了流式的数据,后续的DOM树构建、CSS计算、渲染、合成、绘制,都是尽可能地流式处理前一步的产出:即不需要等到上一步骤完全结束,就开始处理上一步的输出,这样我们在浏览网页时,才会看到逐步出现的页面。
HTTP
协议
HTTP协议是基于TCP协议出现的,对TCP协议来说,TCP协议是一条双向的通讯通道,HTTP在TCP的基础上,规定了Request-Response的模式。这个模式决定了通讯必定是由浏览器端首先发起的。
http
协议格式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jhtG7FeP-1581997624195)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200216221848663.png)]
HTTP Status code
(状态码)和 Status text
(状态文本)
- 1xx:临时回应,表示客户端请继续。
- 2xx:请求成功。
- 200:请求成功。
- 3xx: 表示请求的目标有变化,希望客户端进一步处理。
- 301&302:永久性与临时性跳转。
- 304:跟客户端缓存没有更新。
- 4xx:客户端请求错误。
- 403:无权限。
- 404:表示请求的页面不存在。
- 5xx:服务端请求错误。
- 500:服务端错误。
- 503:服务端暂时性错误,可以一会再试。
1xx :被浏览器
http
库直接处理掉了,不会让上层应用知晓2xx : 网页请求成功的标志
3xx : 301 、302 俩个状态表示当前资源已经被转移,只不过一个是永久性转移,一个是临时性转移。实际上301更接近于报错,提示客户端下次别请求了
304:客户端本地已经有缓存的版本,并且
Request
中告诉了服务端,当服务端通过时间或tag
,发现没有更新的时候,就会返回一个不包含body
的304状态
http Head (请求头)
-
Request Header
-
Response Header
HTTP Request Body
http
请求的body
主要用于提交表单场景实际上,http
请求的body是比较自由的,只要浏览器端发送的body服务端认可就可以了。一些常见的body格式是:
application/json
application/x-www-form-urlencoded
multipart/form-data
text/xml
我们使用html
的form标签提交产生的html
请求,默认会产生 application/x-www-form-urlencoded
的数据格式,当有文件上传时,则会使用multipart/form-data
。
HTTPS
在HTTP协议的基础上,HTTPS和HTTP2规定了更复杂的内容,但是它基本保持了HTTP的设计思想,即:使用上的Request-Response模式。
我们首先来了解下HTTPS。HTTPS有两个作用,一是确定请求的目标服务端身份,二是保证传输的数据不会被网络中间节点窃听或者篡改。
HTTPS是使用加密通道来传输HTTP的内容。但是HTTPS首先与服务端建立一条TLS加密通道。TLS构建于TCP协议之上,它实际上是对传输的内容做一次加密,所以从传输内容上看,HTTPS跟HTTP没有任何区别。
HTTP2
HTTP 2.0 最大的改进有两点,一是支持服务端推送,二是支持TCP连接复用。
服务端推送能够在客户端发送第一个请求到服务端时,提前把一部分内容推送给客户端,放入缓存当中,这可以避免客户端请求顺序带来的并行度不高,从而导致的性能问题。
TCP连接复用,则使用同一个TCP连接来传输多个HTTP请求,避免了TCP连接建立时的三次握手开销,和初建TCP连接时传输窗口小的问题。
Note: 其实很多优化涉及更下层的协议。IP层的分包情况,和物理层的建连时间是需要被考虑的。
如何解析请求回来的html
代码,dom
树又是如何构建的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wrO8692E-1581997624200)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200216233153149.png)]
浏览器是如何把CSS规则应用到节点上,并给这棵朴素的DOM树添加上CSS属性的。
整体过程
构建DOM的过程是:从父到子,从先到后,一个一个节点构造,并且挂载到DOM树上的,那么这个过程中,我们是否能同步把CSS属性计算出来呢?
答案是肯定的
在这个过程中,我们依次拿到上一部构造好的元素,去检查它匹配到了哪些规则,再根据规则的优先级,做覆盖和调整。所以,从这个角度看,所谓的选择器,应该被理解成“匹配器”才更合适。
- 空格: 后代,选中它的子节点和所有子节点的后代节点。
- >: 子代,选中它的子节点。
- +:直接后继选择器,选中它的下一个相邻节点。
- ~:后继,选中它之后所有的相邻节点。
- ||:列,选中表格中的一列。
【注】:选择器的出现顺序,必定跟构建DOM
树的顺序一致,这是一个CSS
设计的原则,即保证选择器在dom
树构建到当前节点时,已经可以准确判断是否匹配,不需要后续节点信息
绘制
有一个一度非常流行于前端群体的说法,讲做CSS性能优化,应该尽量避免"重排"和"重绘,而实际上,这个说法大体不能算错,却不够准确。
因为,实际上,“绘制”发生的频率比我们想象中要高得多。我们考虑一个情况:鼠标划过浏览器显示区域。这个过程中,鼠标的每次移动,都造成了重新绘制,如果我们不重新绘制,就会产生大量的鼠标残影。
这个时候,限制绘制的面积就很重要了。如果鼠标某次位置恰巧遮盖了某个较小的元素,我们完全可以重新绘制这个元素来完成我们的目标,当然,简单想想就知道,这种事情不可能总是发生的。
计算机图形学中,使用的方案就是“脏矩形”算法,也就是把屏幕均匀地分成若干矩形区域。
当鼠标移动、元素移动或者其它导致需要重绘的场景发生时,我们只重新绘制它所影响到的几个矩形区域就够了。比矩形区域更小的影响最多只会涉及4个矩形,大型元素则覆盖多个矩形。
设置合适的矩形区域大小,可以很好地控制绘制时的消耗。设置过大的矩形会造成绘制面积增大,而设置过小的矩形则会造成计算复杂。
我们重新绘制脏矩形区域时,把所有与矩形区域有交集的合成层(位图)的交集部分绘制即可。