浏览器:输入url到页面显示的过程

852 阅读5分钟

从输入url到页面显示无非就分成两个部分:

  1. 客户端--->服务器
  2. 服务器--->客户端--->显示

这里我以一种比较通俗的语言进行解释。 首先比如你在浏览器地址栏输入了www.google.com访问谷歌对吧,这里先假设你看过我写的计网五层协议栈,你输入的这个url,浏览器要通过这个url找到对应的服务器,那具体怎么找呢?光看这个url好像就是找google服务器,但其实并不然,计网才不认这个东西,计网只认得IP,MAC,端口等东西,因为你一切在应用层传输的数据,都是基于底下的协议的,tcp协议,ip协议,以太网协议,所以,由应用层发出的,就要一层一层往下封装。

DNS解析

上面说了,你只有一个url,www.google.com那IP地址呢?没有IP地址你是找不到服务器的,那么DNS解析其实就是对输入的url进行解析找出IP地址的一个过程,这里DNS解析的话我大概总结一些它的过程,在解析过程中,按照浏览器缓存、系统缓存、路由器缓存、ISP(运营商)DNS缓存、根域名服务器、顶级域名服务器、主域名服务器的顺序,逐步读取缓存,直到拿到IP地址。具体的DNS解析过程可以自行去了解

生成请求报文

接着,应用层就可以针对目标的web服务器生成HTTP请求报文了。

建立TCP连接

传输层通过tcp三次握手与服务器建立连接

网络层到物理层封装并传输数据

接着就是一个封装数据包的过程,添加IP地址,添加MAC地址,然后物理层将封装好的数据包转换为光电信号进行传输

服务器到客户端响应

服务器通过对比接收到的数据包的ip和mac地址后,对数据包进行拆解等操作,最后服务器进行响应,返回客户端所需的内容,比如要返回一个google的首页,接着就通过应用层,传输层,网络层,链路层,物理层进行服务器到客户端的数据传输

浏览器渲染

浏览器接收到服务器的数据包后,确认好ip,mac等地址后,就要进行资源的渲染,接下来重点讲讲浏览器接收到资源后的渲染过程

这里我浏览了网上的几篇关于浏览器渲染的文章,感觉也都说得差不多,大致可以分为五个步骤:

  • 解析html,css,js,构建DOM Tree和CSSOM Tree
  • 构建Render树
  • 构建RenderLayer树
  • 布局
  • 渲染

DOM & CSSOM Tree

首先解析HTML文档,所做的其实就是词法语义分析,找开始标签和结束标签,每一个标签都可以当作是一个token,浏览器会给每个token标注是开始标签还是结束标签,然后再去对每个token(进行DFS)生成Node(也就是树结点),最终把所有的token都用完,DOM树也构建完了

CSSOM Tree构建过程和DOM树构建过程相似,它最终是将每个CSS样式都附着到了DOM Tree的对应节点上。这两个过程中,有几个注意点:

  • 当遇到script或link标签时,就会根据地址去加载资源,若script标签没有async或defer属性,就会执行玩标签内代码再继续构建DOM Tree
  • 浏览器必须等到CSSOMTree构建完毕后才能进入下一阶段
  • 如果JS试图在CSSOMTree未构建完毕时操作CSS,则浏览器会暂停JS运行和DOMTree构建,并等待CSSOM构建完成

可见,JS脚本在HTML中的位置十分重要

Render Tree

现在我们有两棵树:DOM和CSSOM,这两棵树其实还不能直接用于排版和渲染,浏览器还会生成另一颗树:Render Tree。Render树其实可以看做成是DOM树和CSSOM树的结合,不过它只构建能显示的DOM节点

  • Render树上的每一个节点未RenderObject
  • RenderObject和每一个可见的DOM一一对应,比如一些<html><script><link>标签就是不可见的,会被忽略掉,还有设置了display:none的标签也会被忽略

此时的Render Tree上已经有了网页上可见元素的内容和位置信息,排版引擎会根据Render树的内容和结构精确的计算出各个元素应该出现在网页的哪个位置

RenderLayer树

到这里,浏览器的渲染引擎其实还不是直接使用Render树进行绘制 为了方便处理Positioning,Clipping,Overflow-scroll,CSS Transfrom/Opacrity/Animation/Filter,Mask or Reflection,Z-indexing等属性,浏览器需要生成另外一棵树:RenderLayer树

浏览器会为一些特定的RenderObject生成对应的RenderLayer

  • 页面根节点
  • 具有css的一些布局属性
  • 透明
  • 有溢出
  • 有css滤镜
  • 包含一个canvas元素使得节点拥有视图上下文
  • 包含video元素

满足上面条件之一,这个RenderObject就会生成一个RenderLayer,那些没有生成Layer的RenderObject就会从属于父节点的RenderLayer 浏览器渲染引擎在布局和渲染时会遍历整个RenderLayer树,访问每一个RenderLayer,再遍历从属于这个Layer的RenderObject,再绘制每一个RenderObject,最后你可以这样理解:Layer决定布局,Object决定具体内容

布局

这一步其实就是生成每个节点的盒模型,计算其在窗口的确切位置和大小,将所有数据转换为屏幕上的绝对像素

渲染

最后一步就是浏览器调用Paint方法进行节点的绘制了

至此,从url输入到页面显示的过程就完成了