正文
- URL 解析
DNS 查询
TCP 连接
处理请求
接受响应
渲染页面
一、URL 解析
地址解析: 首 先 判断你输入的是一个合法的 URL 还是一个待搜索的关键词,并且根据你输入的内容进行自动完成、字符编码等操作。 HSTS 由于安全隐患,会使用 HSTS 强制客户端使用 HTTPS 访问页面 其他操作 浏览器还会进行一些额外的操作,比如安全检查、访问限制(之前国产浏览器限制 996.icu)。 检查缓存![25020220723c3eef09820df4ad85a098.png](https://i-blog.csdnimg.cn/blog_migrate/f67816377047002d42a3780e94cd3b8a.png)
![9ed98d971b2a4aa6c3d68741985968b7.png](https://i-blog.csdnimg.cn/blog_migrate/cf0dfbed97cc1ada89ccef78a15302a9.png)
![9ee674e6647668478b9f342a15fb8b0a.png](https://i-blog.csdnimg.cn/blog_migrate/ec5cabe3721848aea696cad6d8cd94f1.png)
- 递归方式:一路查下去中间不返回,得到最终结果才返回信息(浏览器到本地DNS服务器的过程)
- 迭代方式,就是本地DNS服务器到根域名服务器查询的方式。
- 什么是 DNS 劫持
- 前端 dns-prefetch 优化
TCP/IP 分为四层,在发送数据时,每层都要对数据进行封装:
![3805e4d341b077c80820a402bc5cd1a6.png](https://i-blog.csdnimg.cn/blog_migrate/57909605330cfc00abecd17357ce0f6e.png)
1. 应用层:发送 HTTP 请求
在前面的步骤我们已经得到服务器的 IP 地址,浏览器会开始构造一个 HTTP 报文,其中包括:
请求报头(Request Header):请求方法、目标地址、遵循的协议等等
请求主体(其他参数)
其中需要注意的点:
浏览器只能发送 GET、POST 方法,而打开网页使用的是 GET 方法
2. 传输层:TCP 传输报文
传输层会发起一条到达服务器的 TCP 连接,为了方便传输,会对数据进行分割(以报文段为单位),并标记编号,方便服务器接受时能够准确地还原报文信息。
在建立连接前,会先进行 TCP 三次握手。
“关于 TCP/IP 三次握手,网上已经有很多段子和图片生动地描述了。
相关知识点:
”
SYN 泛洪攻击
3. 网络层:IP协议查询Mac地址
将数据段打包,并加入源及目标的IP地址,并且负责寻找传输路线。
判断目标地址是否与当前地址处于同一网络中,是的话直接根据 Mac 地址发送,否则使用路由表查找下一跳地址,以及使用 ARP 协议查询它的 Mac 地址。
“注意:在 OSI 参考模型中 ARP 协议位于链路层,但在 TCP/IP 中,它位于网络层。
”
4. 链路层:以太网协议
以太网协议
根据以太网协议将数据分为以“帧”为单位的数据包,每一帧分为两个部分:
标头:数据包的发送者、接受者、数据类型
数据:数据包具体内容
Mac 地址
以太网规定了连入网络的所有设备都必须具备“网卡”接口,数据包都是从一块网卡传递到另一块网卡,网卡的地址就是 Mac 地址。每一个 Mac 地址都是独一无二的,具备了一对一的能力。
广播
发送数据的方法很原始,直接把数据通过 ARP 协议,向本网络的所有机器发送,接收方根据标头信息与自身 Mac 地址比较,一致就接受,否则丢弃。
注意:接收方回应是单播。
“相关知识点:
”
ARP 攻击
服务器接受请求
接受过程就是把以上步骤逆转过来,参见上图。
四、服务器处理请求
大致流程![4e4891beebc4c90cafee7c2ed3182ef9.png](https://i-blog.csdnimg.cn/blog_migrate/def19dd6a5476e999aba929943ed2ca1.png)
- 验证是否配置虚拟主机
- 验证虚拟主机是否接受此方法
- 验证该用户可以使用该方法(根据 IP 地址、身份信息等)
301
永久重定向响应,浏览器就会根据响应,重新发送 HTTP 请求(重新执行上面的过程)。
URL 重写
然后会查看 URL 重写规则,如果请求的文件是真实存在的,比如图片、html、css、js文件等,则会直接把这个文件返回。
否则服务器会按照规则把请求重写到 一个 REST 风格的 URL 上。
然后根据动态语言的脚本,来决定调用什么类型的动态文件解释器来处理这个请求。
以 PHP 语言的 MVC 框架举例,它首先会初始化一些环境的参数,根据 URL 由上到下地去匹配路由,然后让路由所定义的方法去处理请求。
五、浏览器接受响应
浏览器接收到来自服务器的响应资源后,会对资源进行分析。
首先查看 Response header,根据不同状态码做不同的事(比如上面提到的重定向)。
如果响应资源进行了压缩(比如 gzip),还需要进行解压。
然后,对响应资源做缓存。
接下来,根据响应资源里的 MIME[3] 类型去解析响应内容(比如 HTML、Image各有不同的解析方式)。
六、渲染页面
浏览器内核
![96e1262d8c3dbe5c428ddc91f5de1f04.png](https://i-blog.csdnimg.cn/blog_migrate/f9813bd7eb5f8ee2a08c14d9623baf88.jpeg)
不同的浏览器内核,渲染过程也不完全相同,但大致流程都差不多。
基本流程
![381884d57a1fd0e20b72ac16056c951c.png](https://i-blog.csdnimg.cn/blog_migrate/3b15638ad4ba40d20e4935271a8067c4.png)
6.1. HTML 解析
首先要知道浏览器解析是从上往下一行一行地解析的。
解析的过程可以分为四个步骤:
① 解码(encoding)
传输回来的其实都是一些二进制字节数据,浏览器需要根据文件指定编码(例如UTF-8)转换成字符串,也就是HTML 代码。
② 预解析(pre-parsing)
预解析做的事情是提前加载资源,减少处理时间,它会识别一些会请求资源的属性,比如img
标签的src
属性,并将这个请求加到请求队列中。
③ 符号化(Tokenization)
符号化是词法分析的过程,将输入解析成符号,HTML 符号包括,开始标签、结束标签、属性名和属性值。
它通过一个状态机去识别符号的状态,比如遇到<
,>
状态都会产生变化。
④ 构建树(tree construction)
“注意:符号化和构建树是并行操作的,也就是说只要解析到一个开始标签,就会创建一个 DOM 节点。
”
在上一步符号化中,解析器获得这些标记,然后以合适的方法创建DOM
对象并把这些符号插入到DOM
对象中。
<html><head> <title>Web page parsingtitle>head><body> <div> <h1>Web page parsingh1> <p>This is an example Web page.p> div>body>html>
![fc2ef81e6b47ab0bb7184ba0674716df.png](https://i-blog.csdnimg.cn/blog_migrate/78df3d355841924e95bdc89b73fa08c7.jpeg)
浏览器容错进制
你从来没有在浏览器看过类似”语法无效”的错误,这是因为浏览器去纠正错误的语法,然后继续工作。
事件
当整个解析的过程完成以后,浏览器会通过DOMContentLoaded
事件来通知DOM
解析完成。
6.2. CSS 解析
一旦浏览器下载了 CSS,CSS 解析器就会处理它遇到的任何 CSS,根据语法规范[4]解析出所有的 CSS 并进行标记化,然后我们得到一个规则表。
CSS 匹配规则
在匹配一个节点对应的 CSS 规则时,是按照从右到左的顺序的,例如:div p { font-size :14px }
会先寻找所有的p
标签然后判断它的父元素是否为div
。
所以我们写 CSS 时,尽量用 id 和 class,千万不要过度层叠。
6.3. 渲染树
其实这就是一个 DOM 树和 CSS 规则树合并的过程。
“注意:渲染树会忽略那些不需要渲染的节点,比如设置了
”display:none
的节点。
计算
通过计算让任何尺寸值都减少到三个可能之一:auto
、百分比、px,比如把rem
转化为px
。
级联
浏览器需要一种方法来确定哪些样式才真正需要应用到对应元素,所以它使用一个叫做specificity
的公式,这个公式会通过:
标签名、class、id
是否内联样式
!important
然后得出一个权重值,取最高的那个。
渲染阻塞
当遇到一个script
标签时,DOM 构建会被暂停,直至脚本完成执行,然后继续构建 DOM 树。
但如果 JS 依赖 CSS 样式,而它还没有被下载和构建时,浏览器就会延迟脚本执行,直至 CSS Rules 被构建。
所有我们知道:
CSS 会阻塞 JS 执行
JS 会阻塞后面的 DOM 解析
为了避免这种情况,应该以下原则:
CSS 资源排在 JavaScript 资源前面
JS 放在 HTML 最底部,也就是