web前端开发应该明白的浏览器工作原理

目录
文章目录隐藏
  1. 浏览器工作流程
  2. 浏览器接受 url 开启网络请求线程
  3. 开启网络线程发出一个完整的 http 请求
  4. 五层因特网协议
  5. 网络通讯 HTTP 协议
  6. 构建 DOM 树
  7. 字符流如何解析成词
  8. 构建 CSSOM
  9. 构建渲染树
  10. 布局与绘制
  11. 总结

作为前端开发,我们平常跟浏览器打交道的时间也是最多的。在前端面试中,一个较为经典的问题:在浏览器地址中输入 url 地址,敲回车,发生了什么?浏览器究竟做了什么?相信很多人脑海里都会出现个大概的轮廓,可是一到细化具体的过程就答不上来。那么,作为前端开发者,应该从哪些方面延伸来回答这个问题呢?

浏览器工作流程

对于浏览器来说,当在地址栏输入 url 地址,浏览器所做的事情就是把一个 url 变成一个在屏幕上显示的网页,大致的过程是这样的:

web 前端开发应该明白的浏览器工作原理

从 HTTP 请求回来,产生流式的数据,DOM 的构建、CSS 计算、渲染、绘制,都是尽可能的流式处理前一步的产出,不需要等待上一步完全接受才开始处理,所以我们在浏览网页的时候,才会逐步出现页面。

1.浏览器接受 url 开启一个网络请求线程

2.浏览器发出一个完整的 http 请求

3.服务器接收请求到后台接收请求

4.使用 http 请求请求页面

5.把请求回来的 html 代码解析成 DOM 树

6.CSS 的可视化格式模型解析

7.根据 CSS 属性对元素进行渲染,得到内存中的位图

8.对位图的合成

9.绘制页面

浏览器接受 url 开启网络请求线程

第一点主要涉及的是浏览器的进程、线程模型以及 JS 的运行机制:

多进程的浏览器

大多数浏览器是多进程的,有一个主控进程,以及每一个 tab 页面都会新开一个进程(某些情况下多个 tab 会合并进程)

进程可能包括主控进程,插件进程,GPU,tab 页(浏览器内核)等等。

  • Browser 进程:浏览器的主进程(负责协调、主控),只有一个
  • 第三方插件进程:每种类型的插件对应一个进程,仅当使用该插件时才创建
  • GPU 进程:最多一个,用于 3D 绘制
  • 浏览器渲染进程(内核):默认每个 Tab 页面一个进程,互不影响,控制页面渲染,脚本执行,事件处理等(有时候会优化,如多个空白 tab 会合并成一个进程)

多线程的浏览器内核

每一个 tab 页面可以看作是浏览器内核进程,然后这个进程是多线程的,它有几大类子线程:

  • GUI 线程
  • JS 引擎线程
  • 事件触发线程
  • 定时器线程
  • 网络请求线程

开启网络线程发出一个完整的 http 请求

该部分主要包括:dns 查询、tcp/ip 请求构建、五层因特网等内容

DNS 查询

如果输入的是域名,需要进行 dns 解析成 IP,大致流程:

  • 如果浏览器有缓存,直接使用浏览器缓存,否则使用本机缓存,再没有的话就是用 host
  • 如果本地没有,就向 dns 域名服务器查询(当然,中间可能还会经过路由,也有缓存等),查询到对应的 IP。

tcp/ip 请求

这里的 tcp/ip 请求需要了解 3 次握手规则建立连接以及断开连接时的四次挥手。

一、为什么需要三次握手?

假设有这样的一个场景,client 发出的第一个请求链接报文段没有丢失,而是因为在网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才打到 sever,这个报文本应该是失效的,如果不是三次握手而是两次握手,会让客服端和服务端再次建立连接,导致不必要的错误和资源的浪费。如果采用的是三次握手,就算是失效的那个报文段发送过来了,服务端收到了那个失效的报文并回复了确认报文,由于 client 不会再次发出确认,由于服务器收不到确认,就知道客户端并没有请求连接。

二、何为三次握手?

1、客户端发送一个 SYN 标志的报文到服务器,这是三次握手的第一个报文;

2、服务端接收到请求,回应一个 ACK 标志和 SYN 标志的报文给客户端,询问客户端是否准备好传输数据。这是三次握手的第二个报文;

3、客户端回应服务端一个 ACK 标志的报文,表示可以传输了,这是第三个报文;

tcp/ip 请求需要了解 3 次握手规则建立连接以及断开连接时的四次挥手

三、为什么需要四次挥手?

由于 TCP 连接是全双工的,因此需要每个方向独立的关闭,当一方完成它的数据传送任务后就能发送一个 FIN 信号来终止这个方向上的连接,收到一个 FIN 仅仅是意味着这一个方向上没有数据的流动,但任然可以传输数据。首先进行的是关闭一方的主动关闭,而另一方执行被动关闭。那为什么在握手的时候 ACK 和 SYN 可以一起发送,而这里是分开的呢?再次强调 TCP 是全双工模式,接受到 FIN 意味着没有数据发来,但可以继续发送数据。

四、何为四次挥手?

1、客户端发送一个 FIN,用来关闭客户端到服务端的数据传送,客户端进入 FIN-WAIT-1 终止等待 1 状态;

2、服务端接受到 FIN 信号,并回应一个 ACK,此时,客户端进入 CLOSE-WAIT 等待关闭状态;

3、客户端收到服务端的确认信号后,客户端进入 FIN-WAIT-2 终止等待 2 状态;服务端将最后的数据发送完以后,发出 FIN 信号报文,进入 LAST-ACK 最后确认状态;

4、客户端收到服务端发送的 FIN 信号,发出 ACK 确认信号,客户端进入 TIME-WAIT 时间等待状态。此时 TCP 连接并没有释放,必须经过 2*MSL(最长报文段寿命)的时间后,才进入 close 状态。服务端只要接受到客户端的确认信息,立即进入 CLOSE 状态。等撤销 TCB 之后,结束这次的 TCP 连接。可以看到服务端结束 TCP 的时间比客户端早一些。

为什么需要四次挥手

五、为什么客户端还需等待 2MSL?

1、保证客户端最后发送的 ACK 报文能达到服务器,因为这个报文肯能会丢失。在服务端看来,客户端如果没有回应 ACK 报文的话,应该是发送的请求断开的报文没有收到,于是服务器又会重新发送一次,而客户端就能在 2MSL 时间段内收到这个重传的报文。接着给出回应的报文,并重启 2MSL 的计时器。

2、防止已经失效的报文段出现在本次的连接中,客户端发送完最后一个确认报文后,在 2MSL 时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失,这样新的连接中不会出现旧的连接的请求报文。

五层因特网协议

其实这个概念挺难记全的,记不全没关系,但是要有一个整体概念。

其实就是一个概念:从客户端发出 http 请求到服务器接收,中间会经过一系列的流程。

简括就是:从应用层的发送 http 请求,到传输层通过三次握手建立 tcp/ip 连接,再到网络层的 ip 寻址,再到数据链路层的封装成帧,最后到物理层的利用物理介质传输。

当然,服务端的接收就是反过来的步骤。

五层因特尔协议栈其实就是:1.应用层(dns,http)2.传输层(tcp,udp)建立 tcp 连接(三次握手)3.网络层(IP,ARP)IP 寻址 4.数据链路层(PPP)5.物理层

OSI 七层框架:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。

表示层:主要处理两个通信系统中交换信息的表示方式,包括数据格式交换,数据加密与解密,数据压缩与终端类型转换等

会话层:它具体管理不同用户和进程之间的对话,如控制登陆和注销过程

网络通讯 HTTP 协议

HTTP 协议是基于 TCP 协议出现的,在 TCP 的基础上规定了 Request-Response 的模型,决定了通讯必须由浏览器端发起的,首先来了解下 HTTP 协议的格式:

HTTP 协议格式

HTTP 协议大致可以分成以下部分:其中 path 是请求路径、version 是固定的字符串,依次介绍下面的每个部分:

网络通讯 HTTP 协议

HTTP Method 请求方法

在 requestline 里面的方法部分,表示 HTTP 的操作类型,常见的几种请求方法如下:

  • GET:浏览器通过地址访问页面均属于 get 请求
  • POST:常见的表单提交
  • HEAD:跟 get 类似,区别在于只返回请求头
  • PUT:表示添加资源
  • DELETE:表示删除资源
  • CONNECT:多用于 HTTPS 和 WebSocket
  • OPTIONS
  • TRACE

HTTP Status code 状态码

常见的状态码有以下几种:

  • 1xx:临时回应
  • 2xx:请求成功,如 200
  • 3xx:请求目标有变化,如 302 和 301 表示临时和永久重定向,304 表示客户端没有更新内容
  • 4xx;请求错误,如 403 无权限,404 访问的资源不存在
  • 5xx:服务端错误,如 500 服务端错误,503 服务端暂时错误等

前端开发中,最熟悉的系列无非是大家都喜欢的 200 请求成功的标志,在面试中,问得较多的是 304 缓存问题和 301、302 重定向的问题。

HTTP HEAD(HTTP 头)

HTTP 头可以看做是一个键值对,在 HTTP 标准中,Request Header 如下图:

HTTP HEAD(HTTP 头)

Response Header 如下图:

Response Header 如下图

在实际的开发中,完整的列表可以参考 rfc2616 标准。

HTTP Request Body

HTTP 请求的 body 主要用于表单的提交,常见的 body 格式:

  • application/json
  • application/x-www-form-urlencoded:使用 form 标签提交的 html 请求,默认产生
  • multipart/form-data:当有文件上传时,使用的格式

HTTPS

HTTPS 在 HTTP 的基础上增加了两个作用,一是确定请求的目标服务端身份,二是保证传输的数据不会被篡改或者窃听,该协议使用加密通道来传输 HTTP 内容,所以首先需要与服务端简历 TLS 加密通道。可以在此处查看详情:https://tools.ietf.org/html/rfc2818

HTTP2

HTTP2 是 HTTP1.1 的升级版,有两大改进:一是支持服务端推送,二是支持 TCP 链接复用:则使用同一个 TCP 链接来传输多个 HTTP 请求。

构建 DOM 树

当浏览器使用 HTTP 向服务端请求页面后,那么如何去解析请求回来的 HTML 代码、构建 DOM 树呢?

构建 DOM 树

字符流如何解析成词

首先浏览器读取获取的 HTML,根据指定的文件编码方式如 UTF-8 转换为字符流,再将字符串转换为词 Token。那什么是词?词是编译原理中的最小单元,如标签开始、属性、标签结束、注释、CDATA 节点。Token 会标识出当前 Token 的种类。举个列子:

<p class="a" >hello</p>

这里就可以拆分成<p(p 标签的开始)、class=”a”(属性)、 style=”font-size: inherit;color: inherit;line-height: inherit;”>(p 标签的结束)、hello(文本)、</p>(结束标签)</p(p 标签的开始)、class=”a”(属性)、>

构建 DOM 树

接下来就是将词变成 DOM 树。在构建 DOM 树时,是一边生成 Token 一边消耗 Token 来生成节点的。

<html>
<head>
    <title>Web page parsing</title>
</head>
<body>
    <div>
        <h1>Web page parsing</h1>
        <p>This is an example Web page.</p>
    </div>
</body>
</html>

构建的 DOM 树:

构建的 DOM 树

构建 CSSOM

在构建完 DOM 树,当前的对象只包含节点和属性,没有任何样式信息,那么浏览器是如何给 DOM 树添加 CSS 属性呢?我们知道浏览器是流式的处理整个过程,我们拿到 DOM 树构造好的元素,依次去检查他匹配的规则,再根据规则的优先级,做覆盖和调整。

构建渲染树

当 CSSOM 树和 DOM 树都得到之后,将两个树进行合并就得到了渲染树:

构建渲染树

布局与绘制

当浏览器生成渲染树以后,就会根据渲染树来进行布局。在这个过程中,每一个元素都要要弄清楚各个节点在页面中的确切位置和大小,把对应的盒变为相应的位图。一个元素可能对应多个盒(如内联元素,可能被分成多行)每一个盒都对应着一个位图。合成把部分位图合成变成合成层。最终的绘制过程就是把位图合成层绘制到屏幕上。

总结

浏览器的工作流程大致就是:

构建 DOM 树-构建 CSSOM-构建渲染树-布局-绘制

「点点赞赏,手留余香」

23

给作者打赏,鼓励TA抓紧创作!

微信微信 支付宝支付宝

还没有人赞赏,快来当第一个赞赏的人吧!

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
码云笔记 » web前端开发应该明白的浏览器工作原理

2 评论

  1. 做前端开发必须懂得知识 :razz:

回复 秦璐 取消回复