美文网首页让前端飞JavaScript 进阶营前端开发笔记
浏览器渲染页面过程剖析(当用户在地址栏输入URL点击回车后。。。

浏览器渲染页面过程剖析(当用户在地址栏输入URL点击回车后。。。

作者: Rocky_Wong | 来源:发表于2018-08-23 10:07 被阅读2次

    整体过程

    1. 用户输入URL地址

    2. 对URL地址进行DNS域名解析

    3. 建立TCP连接(三次握手)

    4. 浏览器发送HTTP请求报文

    5. 服务器返回HTTP响应报文

    6. 关闭TCP连接(四次挥手)

    7. 浏览器解析文档资源并渲染页面

    DNS域名解析

    为什么需要DNS解析域名为IP地址?

    网络通讯大部分是基于TCP/IP的,而TCP/IP是基于IP地址的,所以计算机在网络上进行通讯时只能识别如“202.96.134.133”之类的IP地址,而不能认识域名。我们无法记住10个以上IP地址的网站,所以我们访问网站时,更多的是在浏览器地址栏中输入域名,就能看到所需要的页面,这是因为有一个叫“DNS服务器”的计算机自动把我们的域名“翻译”成了相应的IP地址,然后调出IP地址所对应的网页。

    DNS了解一下

    DNS( Domain Name System)是“域名系统”的英文缩写,是一种组织成域层次结构的计算机和网络服务命名系统,它用于TCP/IP网络,它所提供的服务是用来将主机名和域名转换为IP地址的工作。

    DNS解析过程

    浏览器收到URL后,先去本地host文件中查找是否有对应的域名IP关系,如果有即向IP地址发起请求;如果没有,将到DNS服务器中查找。

    DNS分为本地DNS服务器,根DNS服务器和各个子DNS服务器。

    从浏览器到本地DNS服务器属于递归查询,而DNS服务器之间属于迭代查询。例如对www.esaonwong.com这个域名进行解析,步骤如下:

    1. 浏览器本地DNS服务器发送www.esaonwong.comDNS查询报文

    2. 本地DNS服务器根DNS服务器转发该报文

    3. 根DNS服务器解析到com后缀,告知本地DNS服务器comDNS服务器的IP地址

    4. 本地DNS服务器comDNS服务器转发该报文

    5. comDNS服务器解析到www.esaonwong.com后缀,告知本地DNS服务器www.esaonwong.comDNS服务器的IP地址

    6. 本地DNS服务器www.esaonwong.comDNS服务器转发该报文

    7. www.esaonwong.comDNS服务器解析到www.esaonwong.com后缀,告知本地DNS服务器www.esaonwong.com的IP地址

    8. 本地DNS服务器返回对应的IP地址给浏览器

    建立TCP连接

    通俗理解

    TCP连接就是我们常谈的三次握手过程🤝

    客户端:“你好在吗?我要给你发送东西咯~!”

    服务端:“嗯嗯我在啊!你发吧~”

    客户端: “嗯啊-8-”

    图解

    1. 客户端发送连接请求报文段,将SYN位置为1,Seq为x;然后,客户端进入SYN_SEND状态,等待服务器的确认;
    2. 服务器收到SYN报文段。服务器收到客户端的SYN报文段,需要对这个SYN报文段进行确认,设置ACK为x+1;同时,自己自己还要发送SYN请求信息,将SYN位置为1,Seq为y;服务器端将上述所有信息放到一个报文段(即SYN+ACK报文段)中,一并发送给客户端,此时服务器进入SYN_RECV状态;
    3. 客户端收到服务器的SYN+ACK报文段。然后将ACK设置为y+1,向服务器发送ACK报文段,这个报文段发送完毕以后,客户端和服务器端都进入ESTABLISHED状态,完成TCP三次握手。

    为什么是三次握手而不是两次,四次呢?

    在谢希仁著《计算机网络》第四版中讲“三次握手”的目的是“为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误”。在另一部经典的《计算机网络》一书中讲“三次握手”的目的是为了解决“网络中存在延迟的重复分组”的问题。

    在谢希仁著《计算机网络》书中同时举了一个例子,如下:

    “已失效的连接请求报文段”的产生在这样一种情况下:client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。”

    在知乎上有个生动的比喻:

    三次握手:
    “喂,你听得到吗?”
    “我听得到呀,你听得到我吗?”
    “我能听到你,今天balabala……”

    两次握手:
    “喂,你听得到吗?”
    “我听得到呀”
    “喂喂,你听得到吗?”
    “草,我听得到呀!!!!”
    “你TM能不能听到我讲话啊!!喂!”
    “……”

    四次握手:
    “喂,你听得到吗?”
    “我听得到呀,你听得到我吗?”
    “我能听到你,你能听到我吗?”
    “……不想跟傻逼说话”

    浏览器发送HTTP请求报文

    (略)

    服务器返回HTTP响应报文

    (略)

    关闭TCP连接

    通俗理解

    TCP连接关闭时进行四次握手过程👋

    客户端:“你好,我这边没有数据要传了,我要关闭咯。”

    服务端:“收到~我看一下我这边有没数据要传的。”

    服务端:“我这边也没有数据要传啦,我们可以关闭连接咯~”

    客户端:”ojbk~“

    图解

    1. 主机1(可以使客户端,也可以是服务器端),设置Seq和Ack,向主机2发送一个FIN报文段;此时,主机1进入FIN_WAIT_1状态;这表示主机1没有数据要发送给主机2了;
    2. 主机2收到了主机1发送的FIN报文段,向主机1回一个ACK报文段,Ack为Seq加1;主机1进入FIN_WAIT_2状态;主机2告诉主机1,我“同意”你的关闭请求;
    3. 主机2向主机1发送FIN报文段,请求关闭连接,同时主机2进入LAST_ACK状态;
    4. 主机1收到主机2发送的FIN报文段,向主机2发送ACK报文段,然后主机1进入TIME_WAIT状态;主机2收到主机1的ACK报文段以后,就关闭连接;此时,主机1等待2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,主机1也可以关闭连接了。

    浏览器解析文档资源并渲染页面

    1. HTML解析出DOM Tree

    2. CSS解析出CSSOM Tree

    3. JavaScript代码由JavaScript引擎处理

    4. DOM树建立后根据CSS样式进行构建内部绘图模型,生成RenderObject树

    5. 根据网页层次结构构建RenderLayer树,同时构建虚拟绘图上下文

    6. 依赖2D和3D图形库渲染成图像结果呈现在浏览器中(Painting)

    我们以webkit内核浏览器渲染过程为例

    HTML解析

    HTML Parser的任务是将HTML标记解析成DOM Tree

    CSS解析

    CSS Parser将CSS解析成Style Rules,Style Rules也叫CSSOM(CSS Object Model)。
    StyleRules也是一个树形结构,根据CSS文件整理出来的类似DOM Tree的树形结构

    JavaScript处理

    浏览器解析文档,当遇到script标签的时候,会立即解析脚本,停止解析文档(因为JS可能会改动DOM和CSS,所以继续解析会造成浪费)。
    如果脚本是外部的,会等待脚本下载完毕,再继续解析文档。现在可以在script标签上增加属性 defer或者async。
    脚本解析会将脚本中改变DOM和CSS的地方分别解析出来,追加到DOM Tree和Style Rules上。

    布局(回流)

    创建渲染树后,下一步就是布局(Layout),或者叫回流(reflow,relayout),这个过程就是通过渲染树中渲染对象的信息,计算出每一个渲染对象的位置和尺寸,将其安置在浏览器窗口的正确位置,而有些时候我们会在文档布局完成后对DOM进行修改,这时候可能需要重新进行布局,也可称其为回流,本质上还是一个布局的过程,每一个渲染对象都有一个布局或者回流方法,实现其布局或回流。

    绘制(重绘)

    在绘制阶段,系统会遍历呈现树,并调用呈现器的“paint”方法,将呈现器的内容显示在屏幕上。绘制工作是使用用户界面基础组件完成的。
    CSS2 规范定义了绘制流程的顺序。绘制的顺序其实就是元素进入堆栈样式上下文的顺序。这些堆栈会从后往前绘制,因此这样的顺序会影响绘制。块呈现器的堆栈顺序如下:

    1. 背景颜色
    2. 背景图片
    3. 边框
    4. 子代
    5. 轮廓

    Reflow的成本比Repaint的成本高得多的多。DOM Tree里的每个结点都会有reflow方法,一个结点的reflow很有可能导致子结点,甚至父点以及同级结点的reflow。在一些高性能的电脑上也许还没什么,但是如果reflow发生在手机上,那么这个过程是非常痛苦和耗电的。 所以,下面这些动作有很大可能会是成本比较高的。

    • 当你增加、删除、修改DOM结点时,会导致Reflow或Repaint

    • 当你移动DOM的位置,或是搞个动画的时候。

    • 当你修改CSS样式的时候。

    • 当你Resize窗口的时候(移动端没有这个问题),或是滚动的时候。

    • 当你修改网页的默认字体时。

    • 注:display:none会触发reflow,而visibility:hidden只会触发repaint,因为没有发现位置变化。

    基本上来说,reflow有如下的几个原因:

    • Initial。网页初始化的时候。

    • Incremental。一些Javascript在操作DOM Tree时。

    • Resize。其些元件的尺寸变了。

    • StyleChange。如果CSS的属性发生变化了。

    • Dirty。几个Incremental的reflow发生在同一个frame的子树上。

    参考文章

    DNS原理及其解析过程

    通俗大白话来理解TCP协议的三次握手和四次分手

    TCP的三次握手四次挥手

    浏览器渲染页面过程与页面优化

    细说浏览器输入URL后发生了什么

    (完)

    相关文章

      网友评论

        本文标题:浏览器渲染页面过程剖析(当用户在地址栏输入URL点击回车后。。。

        本文链接:https://www.haomeiwen.com/subject/odtuiftx.html