从输入URL到页面呈现发生了什么?

从输入URL到页面呈现发生了什么?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a4q5zyf3-1629881996505)(D:\沸点前端\浏览器\img\流程图.png)]

按下回车后,用户发出URL请求到页面开始解析的这个过程,叫做导航

前导

  • 一切都从浏览器进程开始:浏览器中tab外面发生的一切都是由浏览器进程控制的。浏览器进程有很多负责不同工作的线程,其中包括绘制浏览器顶部按钮和导航栏输入框等组件的UI线程、管理网络请求的网络线程、以及控制文件读写的存储线程等。当你在导航栏里面输入一个URL的时候,其实就是UI线程在处理你的输入。

1. 用户输入-浏览器进程

用户在地址栏输入关键字后,地址栏会判断输入的关键字是搜索内容还是请求的URL

  • 如果是搜索内容,地址栏会使用浏览器默认的搜索引擎来合成新的带搜索关键字的URL。
  • 如果输入内容符合URL规则,则会根据规则合成完整的URL(比如自动拼接http://)。

然后浏览器进程会通过进程间通信(IPC)把URL请求发送给网络进程,网络进程接收到URL后,才会发起真正的URL请求。

2. 网络请求-网络进程

1.1 输入url后,浏览器会解析出协议、主机、端口、路径等信息,并构造一个HTTP请求
  • 发送http请求前,会根据请求头的expirescache-Control判断是否命中强缓存
  • 若没有命中则发起请求,根据请求头的Last-ModifiedETag判断是否命中协商缓存
  • 若前两个都没有命中,则直接从服务端获取资源
1.2 DNS解析

我们的浏览器、操作系统、路由器都会缓存一些URL对应的IP地址,统称为DNS高速缓存。

在发送HTTP请求之前,浏览器会先发送一个UDP包给DNS域名解析服务器去寻找对应的IP地址,然后在发起HTTP请求。

1.3 发起HTTP请求

如果请求协议是HTTPS,那么还需要建立TLS连接。

  • 首先三次握手建立TCP连接。
  • 建立完毕后,浏览器可以和服务器开始通信,即开始发送HTTP请求。
  • HTTP到达服务器后,服务器进行响应处理。响应完后,TCP连接可断开也可以不断开,由字段connection决定。

一般来讲,为了优化导航时间,浏览器进程向网络进程提供URL后,就会开始准备渲染进程。

3. 解析文件-渲染进程

  • 浏览器进程向渲染进程发送“提交文档”的消息,渲染进程接受到“提交文档”后,会和网络进程建立传输数据的“管道”。

  • 等文档数据传输完成之后,渲染进程会返回“确认提交”的消息给浏览器进程。

  • 浏览器进程收到“确认提交”后,会更新浏览器的界面状态,包括安全状态、地址栏url、前进后退状态、更新web页面等。

2.1 构建DOM树

由于浏览器无法直接理解HTML字符串,所以需要将其转换成可方便操作的DOM树,DOM树本质是以document为根节点的多叉树。

  • 转换:浏览器从磁盘或网络中读取HTML的原始字节,并根据文件的指定编码将它们转换成各个字符
  • 令牌化:浏览器将字符转换成W3C、HTML5标准规定的各种令牌。每个令牌都有特殊含义和一组规则。
  • 词法分析:发出的令牌根据规则转换成定义其属性和规则的对象
  • DOM树构建:由于HTML标记定义不同标记之间的关系,创建的对象连接在一个树结构内。
2.2 样式计算
  • 格式化样式表:由于浏览器不理解CSS样式文本,因此渲染引擎接受到CSS文本后第一件事就是将其转化为一个结构化的对象,即styleSheets
  • 标准化样式属性:有些CSS属性值不容易被渲染引擎理解,因此需要将他们标准化,比如em变为px、red变为#ff0000等。
  • 计算每个节点的具体样式:根据继承层叠规则来计算每个节点的样式,并被保存在ComputedStyle的结构内。
2.4 生成布局树并布局计算

生成DOM树ComputedStyle后,接下来要做的就是通过浏览器的布局系统确定元素的位置,也就是生成一棵布局树(Layout Tree)。

布局树生成的大致流程如下:

  • 生成初步布局树:遍历 DOM 树中的所有可见节点,并把这些节点加到布局树。
  • 布局计算:当有一棵完整的布局树后,会计算布局树节点的坐标位置并重新写回布局树中。

4. 渲染过程-渲染进程

分层

有了布局树之后,由于3D效果或层叠效果存在,还会对特定的节点进行分层,构建一颗图层树(Layer Tree)。

一般情况下,节点的图层会默认属于父节点的图层,但有时一些节点会被提升为单独的一层:

  • 拥有层叠上下文属性的元素
    • z-index; opacity; transform; filter; isolation; will-change等等
  • 需要剪裁(clip)的地方
    • 比如文字超出div大小,超出部分需要为剪裁。这种情况下,渲染引擎会为文字部分单独创建一个层,如果出现滚动条,滚动条也会被提升为单独的层。
  • 层叠等级低的节点被提升为单独的图层之后,那么所有层叠等级比它高的节点都会成为一个单独的图层。这潜在层爆炸的危险。
生成绘制列表

完成图层树的构建后,渲染引擎会将图层的绘制拆分成一个个绘制指令

格栅化(raster)

绘制操作都是由渲染进程中的合成线程来完成。

生成绘制列表后,渲染进程的主线程会把绘制列表**提交(commit)**给合成线程开始绘制。

  • 分块:由于页面实际大小要大于视口(viewport),一次性绘制出页面再展示开销会很大。基于这个原因,合成线程会将图层划分为图块(tile)。图块大小通常为256*256或者512*512。
  • 格栅化:合成线程会选择视口附近的图块,把它交给格栅化线程池来生成位图(由许多像小方块一样的像素组成的图形)。

但通常,格栅化过程都会使用GPU来加速生成,相当于渲染进程把生成图块的指令发送给了GPU进程,使用GPU生成位图的过程叫快速格栅化(GPU格栅化),生成的位图被保存在GPU内存中,最后再发送给合成线程

合成显示
  • 当所有图块都被格栅化后,合成线程会生成一个绘制图块的命令——“DrawQuad”,然后将命令提交给浏览器进程。

  • 浏览器进程有一个叫viz的组件,收到发来的DrawQuad命令后,将页面内容绘制到内存中,最后再将这部分内存发送给显卡。显卡接收到浏览器进程传来的页面后,会合成相应的图像,显示到屏幕上。

大致流程:

  • 渲染进程将HTML内容转换为浏览器可读懂的DOM树结构
  • 渲染引擎将CSS样式表转化为浏览器可理解的styleSheets,计算出DOM节点样式
  • 创建布局树,并计算元素的几何位置
  • 对于布局树进行分层,并生成分层树
  • 为每个图层生成绘制列表,并将其交给合成线程
  • 合成线程将图层分为图块,并在格栅化线程池中将图块转换成位图
  • 合成线程发送DrawQuad指令给浏览器进程
  • 浏览器进程根据DrawQuad消息将页面生成并保存在内存中,再发给显卡,显示到屏幕上
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值