参考文章
总体步骤
-
输入
1.1 url 解析
-
请求过程
2.1 dns 解析
2.2 tcp建立 (三次握手, 四次挥手)
2.3 请求html文件
-
页面渲染
3.1 DOM
3.2 CSSOM
3.3 执行js
3.4 构建渲染树
3.5 布局(layout)
3.6 绘制 (painting)
步骤详解
- 输入
浏览器会去解析输入的字符串,判断是URL还是搜索关键字,要是解析为URL则开始寻求URL对应的IP地址,否则按照搜索关键字处理交给默认搜索引擎搜索。
- url解析
为什么需要url解析? url 有一定的格式, 只有正确的解析才能获得ip地址
protocol://hostname[:port]path search hash
url 采用什么编码? url采用的是SCCII码编码
- 请求过程
-
dns 解析
- 查询浏览器DNS缓存
- 查询本地系统DNS缓存 (本地hosts文件)
- 向ISP的DNS服务器查询 (ISP: 互联网服务提供商)
- 向根服务器查询: (两种模式)
-
递归查询:客户端只发一次请求,如果根服务器自身没有, 同时知道哪个服务器有,那么根服务器会代替客户,进行递归查找。
-
迭代查询:客户端发一次请求,如果根服务器自身没有, 同时知道哪个服务器有,那么根服务器会告诉客户端地址,客户端自己查找。
-
-
tcp 建立 (tcp是可靠的传输,三次握手和四次挥手就是确保了通信的可靠)
- 三次握手
所谓三次握手(Three-way Handshake),是指建立一个TCP连接时,需要客户端和服务器总共发送3个包。 三次握手的目的是连接服务器指定端口,建立TCP连接,并同步连接双方的序列号和确认号并交换 TCP 窗口大小信息.在socket编程中,客户端执行connect()时。将触发三次握手
- 客户端发送标有 SYN 的数据包,表示我将要发送请求。
- 服务端发送标有 SYN/ACK 的数据包,表示我已经收到通知,告知客户端发送请求。
- 客户端发送标有 ACK 的数据包,表示我要开始发送请求,准备被接受。
为什么不能用两次握手进行连接?
现在把三次握手改成仅需要两次握手。 例子,考虑计算机S和C之间的通信,假定C给S发送一个连接请求分组,S收到了这个分组,并发 送了确认应答分组。按照两次握手的协定,S认为连接已经成功地建立了,可以开始发送数据分组。可是,C在S的应答分组在传输中被丢失的情况下,将不知道S 是否已准备好,不知道S建立什么样的序列号,C甚至怀疑S是否收到自己的连接请求分组。在这种情况下,C认为连接还未建立成功,将忽略S发来的任何数据分组,只等待连接确认应答分组。而S在发出的分组超时后,重复发送同样的分组。
-
四次挥手
TCP的连接的拆除需要发送四个包,因此称为四次挥手(four-way handshake)。客户端或服务器均可主动发起挥手动作,在socket编程中,任何一方执行close()操作即可产生挥手操作。
- 客户端发送请求,申请断开连接,进入等待阶段,此时不会发送数据,但是会继续接收数据。(第一次挥手)
- 服务端接收请求后,告知客户端已明白,此时服务端进入等待状态,不会再接收数据,但是会继续发送数据。(第二次挥手)
- 客户端收到后,进入下一阶段等待。
- 服务端发送完剩余的数据后,告知客户端可以断开连接,此时服务端不会发送和接收数据。(第三次挥手)
- 客户端收到后,告知服务端我开始断开连接。 (第四次挥手)
- 服务端收到后,开始断开连接。
-
请求html等文件
如果文件在缓存里面浏览器直接返回,如果没有,就去后台拿
浏览器首次加载资源成功时,浏览器不仅将资源下载下来,而且把response的header(里面的date属性非常重要,用来计算第二次相同资源时当前时间和date的时间差)一并缓存。
缓存分为强缓存和协商缓存
强缓存:
浏览器不与服务端协商直接取浏览器缓存。
字段:cache-control 和 expires
协商缓存:
浏览器会先向服务器确认资源的有效性后才决定是从缓存中取资源还是重新获取资源。
相关字段: last-modified、 etag、 If-Modified-Since 、If-None-Match
开启协商缓存, 响应头会带有last-modified。 第二次请求时,请求头会带有if-modified-since ,值为上次响应的last-modified值,服务端会比较两者值是否相同。 因为有弊端参考, 所以后面增加了etag比较。 支持etag后,响应头会带有etag, 第二次请求时, 请求头会带有if-none-match,值为上次的etag值, 服务端会比较两者是否命中
- 下一次加载资源时,首先要经过强缓存的处理,cache-control的优先级最高,比如cache-control:no-cache,就直接进入到协商缓存的步骤了,如果cache-control:max-age=xxx,就会先比较当前时间和上一次返回200时的时间差,如果没有超过max-age,命中强缓存,不发请求直接从本地缓存读取该文件(这里需要注意,如果没有cache-control,会取expires的值,来对比是否过期),过期的话会进入下一个阶段,协商缓存
- 协商缓存阶段,则向服务器发送header带有If-None-Match和If-Modified-Since的请求,服务器会比较Etag,如果相同,命中协商缓存,返回304;如果不一致则有改动,直接返回新的资源文件带上新的Etag值并返回200;
- 协商缓存第二个重要的字段是,If-Modified-Since,如果客户端发送的If-Modified-Since的值跟服务器端获取的文件最近改动的时间,一致则命中协商缓存,返回304;不一致则返回新的last-modified和文件并返回200;
-
页面渲染
-
解析 HTML 生成 DOM 树
由于网络进程传输给渲染进程的是 HTML 字符串,所以,渲染进程需要将 HTML 字符串转化成 DOM 树
-
解析 CSS 生成 CSSOM
解析 CSS 文件、style 标签、行内 style 等,生成 CSSOM
-
加载或执行 JavaScript
-
生成渲染树(Render Tree)
生成DOM 树和 CSSOM 之后,需要将两者结合生成渲染树
-
布局(layout)
根据渲染树将节点树的每一个节点布局在屏幕上的正确位置
第一次确定节点的大小和位置的过程称为布局,而第二次被称为回流
-
绘制(painting)
遍历渲染树绘制所有节点,为每一个节点适用对应的样式,这一过程是通过UI后端模块完成
-