快捷指令获取url内容_从输入 URL 到页面展示,中间发生了什么?

61d9e06cbce3d4e8c0428a2755efccdd.png

整体流程大概可描述为:

  1. 用户从浏览器里输入请求信息
  2. 网络进程发起 URL 请求
  3. 服务器响应 URL 请求之后,浏览器进程开始准备渲染进程
  4. 渲染进程准备完毕后,向渲染进程提交页面数据(提交文档阶段)
  5. 渲染进程接受完文档信息后,开始解析页面和加载子资源,完成页面渲染

从输入 URL 到页面展示详细过程

用户输入

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

  • 若判断为搜索内容,地址栏使用默认搜索引擎,合成新的带搜索关键字的 URL(q 后为搜索关键字)https://www.google.com/search?q=google&xxxxxx
  • 若判断内容符合 URL 规则,则地址栏会根据输入内容,合称为完整的 URLwww.baidu.com => https://www.baidu.com/
    输入关键字后回车,标签上的图标变成 loading 状态,此时页面没有立即替换为目标页面;需要等待提交文档阶段结束,页面内容才会被替换。

URL 请求过程

页面请求资源过程,浏览器进程通过 IPC(进程间通信) 把 URL 请求发送至网络进程,网络进程收到后发起真正的 URL 请求。具体过程如下:

  1. 查找本地有无缓存资源。有,返回给浏览器进程。
  2. 没有,直接发起网络请求。
  3. DNS 解析来获取请求域名的服务器 IP 地址。
  4. 若请求协议是 HTTPS,还需要建立 TLS(安全传输层协议) 连接。
  5. 用 IP 地址和服务器建立 TCP 连接。(同一域名同时最多只能建立 6 个连接,超过的排队等待)(通过传输层、网络层等加上相应的头)
  6. 建立连接后,构建请求头、行等信息,将相关 cookie 等数据附加到请求头中,然后发送给服务器
  7. 服务器接受到请求信息后,根据请求信息生成响应数据,发给网络进程。(响应数据又顺着应用层——传输层——网络层——网络层——传输层——应用层的顺序返回到网络进程)
  8. 网络进程接收了响应行、头后便开始解析响应内容。
  9. 若返回的状态时是 301 或 302,则浏览器需要重定向到其他 URL,一切从头开始。
  10. 浏览器根据响应头中的Content-Type字段判断响应体的数据类型;若是application/octet-stream字节流类型,浏览器会按下载类型来处理,该请求会被提交给浏览器的下载管理器,流程结束。若是 HTML,则进入下个流程:准备渲染进程

准备渲染进程 & 提交文档

不同主域名的页面使用不同的渲染进程,主域名相同的使用同一个渲染进程;

  1. 渲染进程准备完毕后,浏览器进程发出提交文档的消息。
  2. 渲染进程收到后,会和网络进程建立传输数据的管道。
  3. 传输完毕后,渲染进程会返回“确认提交”的消息给浏览器进程。
  4. 浏览器进程收到确认的消息后,会更新浏览器界面状态(安全状态、URL、前进后退的历史状态)并更新 web 页面。(此时 web 页面是空白页面)
  5. 导航流程结束,进入渲染阶段。

渲染阶段

按照渲染的时间顺序,流水线可分为:

构建 DOM 树 -> 样式计算 -> 布局 -> 分层 -> 绘制 -> 分块 -> 光栅化 -> 合成等阶段。

每个阶段的流程如下:接收输入的内容 -> 处理 -> 输出内容

构建 DOM 树

接收 html 文件 -> html 解析器解析 -> 输出树状解构的 DOM

样式计算

大体流程:接受 css 文本 -> 计算出 dom 节点的具体样式 -> 输出计算完成后的 DOM 样式

具体步骤如下:

  • 接收 css 文本,将其转为浏览器可理解的结构:stylesheets
    css 三种来源:内联、外部引入、style
  • 转换 stylesheets 中属性值,使其标准化

body { font-size: 2em } p {color:blue;} div { font-weight: bold} // 标准化后 body { font-size: 32px } p {color: rgb(0,0,255);} div { font-weight: 700}

  • 计算出 DOM 树中每个节点的具体样式
    计算遵守 css 继承、层叠两个规则。所有子节点都继承父节点的样式。计算完后输出每个 DOM 节点的样式。

布局

经过上面过程,有了 DOM 树和树中元素的样式,但每个元素的位置还不确定,不足以显示页面。

Chrome 在布局阶段的任务:创建布局树与布局计算。

  • 创建布局树
    遍历 DOM 中的可见节点,将其添加到布局树中。不可见的节点会被忽略,比如:head 标签下的内容、display 为 none 的节点。
  • 布局计算
    计算布局树节点的坐标位置,计算完执行布局时会把运算的结果会重新写入布局树中,所以布局树既是输入内容也是输出内容;

分层

布局完之后不会立即绘制,渲染引擎会为特定的节点生成专用的图层,并生成一棵对应的图层树(LayerTree)。在开发者工具下的 Layers 标签可以看见页面的分层情况,每个节点都有图层,若没有,就属于它父节点的图层。

  • 什么情况下,渲染引擎会为特定节点创建新图层?
  1. 拥有层叠上下文的属性会被提升为单独的一层。
层叠上下文​developer.mozilla.org
62d362ea031ebc383ee753be36eb3c3f.png


层叠上下文让 HTML 具有三维概念,按照自身属性优先级垂直分布在 z 轴上。

f5e8ca31b91518dda25cee4ae9dde4c2.png

2. 需要剪裁(clip)的地方也会被创建为图层。
文字内容比较多,超出显示区域,这时就产生裁剪。渲染引擎会为文字部分单独创建一个层,若出现滚动条,滚动条也会被提升为单独的层。

b834fc28acbbe9bb87549d2bf8a9da0d.png

图层绘制

画图例子:

给你一张纸,画一个背景蓝色,中间为红色的圆,再在圆上画一个绿色三角形,如何画?

  1. 绘制蓝色背景
  2. 在中间绘制红色圆
  3. 在圆上绘制绿色三角形

图层绘制与之类似,将一个图层拆分成很多小的绘图指令,把指令按顺序组成列表去绘制。(每个元素背景、前景、边框都需要单独的绘图指令)
开发者工具 Layers 标签,选中 document 层,可重现绘制过程.

794cbf1f62b6a1595f941b00cbe889de.png
图层绘制过程

栅格化(raster)操作

a088ff9fc5e42659a5a78fc9c729271a.png

绘制列表只用来记录绘制顺序与指令,真正的绘制操作由渲染引擎中的合成线程来完成。如上图,绘制列表准备好后,主线程会把它提交给合成线程。

有的图层很大,页面要使用滚动条滚好久才能到底部;通过视口,用户只能看到一小部分,这种情况下如果绘制所有图层内容,会产生很大开销且没必要。

合成线程如何处理?

合成线程会将图层划分成图块(tile),大小通常为(256x 256, 512 x 512)。

c1218c9673dd4479c8f92ce8016f2e11.png

合成线程会按照视口附近的图块来优先生成位图,实际生成位图的操作由栅格化(将图块转为位图)执行。图块是栅格化执行的最小单位。渲染进程维护了一个栅格化的线程池,所有图块栅格化都在线程池内执行。

栅格化过程会使用 GPU 来加速生成,生成的位图被保留在 GPU 内存中。(GPU 操作在 GPU 进程中,栅格化在渲染进程中,这个过程涉及跨进程操作。)

合成与显示

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

浏览器进程里有个 viz 组件,接收到 DrawQuad 命令后,根据其内容,将页面绘制到内存,最后再将内存显示到屏幕上。

d51268338becc5523a35866c558f4b6a.png

完整渲染流程总结

  1. 渲染进程将 HTML 内容转换为能够读懂的DOM 树结构。
  2. 渲染引擎将 CSS 样式表转化为浏览器可以理解的styleSheets,计算出 DOM 节点的样式。
  3. 创建布局树,并计算元素的布局信息。
  4. 对布局树进行分层,并生成分层树。
  5. 为每个图层生成绘制列表,提交给合成线程。
  6. 合成线程将图层分成图块,并在栅格化线程池中将图块转化为位图。
  7. 合成线程发送绘制图块命令 DrawQuad 给浏览器进程。
  8. 浏览器进程根据 DrawQuad 消息生成页面,并显示到显示器上。

重排、重绘、合成

  • 重排
    更新元素几何属性,开销最大

08438de344f94610359ccbcd9615f8b3.png
  • 重绘
    更新元素颜色

97363ffdc34d477ae37eac49cd2a4b74.png
  • 合成
    直接合成,避开重排重绘。

d13eeebdeb4ac726802d54ceef76740e.png

减少重排、重绘的方法?

  1. 使用 class 操作样式,而不是频繁操作 style
  2. 避免使用 table 布局
  3. 批量dom 操作,例如 createDocumentFragment,或者使用框架
  4. Debounce window resize 事件
  5. 对 dom 属性的读写要分离
  6. will-change: transform 做优化

参考资料

浏览器工作原理与实践

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值