【浏览器】Chrome浏览器的执行机制(内附相关知识点面经串联)

lxf2023-05-06 03:12:01

“开启AdminJS成长之旅!这是我参与「AdminJS · 2 月更文挑战」的第 1 天,点击查看活动详情”

今天在看到菜鸟教程中的

HTML 中的 Javascript 脚本代码必须位于<script></script> 标签之间。Javascript 脚本代码可被放置在 HTML 页面<body><head> 部分中

不禁好奇放在这两者的区别在哪?其实我是从这个小问题入手的,发现这就要谈到浏览器的执行机制

可以理清包括但不仅限于以下问题:

  • 键入URL后浏览器发生了什么(不涉及到网络的那一部分)
  • js文件加载带来的阻塞,阻塞的解决方案
  • Vue虚拟DOM技术的好处

以下内容只是个人理解,要是有错希望大佬们不吝赐教(求生欲极强,主要还是有些没懂的地方)


Chrome浏览器的执行机制

Critical Rendering Path(CRP关键渲染路径)是指:

浏览器获取到html文档(如下图1所示)到屏幕打印出显示用户能看到的内容(如下图2所示)这一过程

图1:浏览器获取到的HTML文件(可以通过鼠标右键页面后选择“查看网页源代码得到”) 【浏览器】Chrome浏览器的执行机制(内附相关知识点面经串联)

图2:浏览器解析后展示的界面 【浏览器】Chrome浏览器的执行机制(内附相关知识点面经串联)

从图1到图2的过程(是不是很神奇,此时我直接起身为浏览器鼓掌!!!)

浏览器在这个过程中主要经历了以下几个子步骤:

  • 构建 DOM 树
  • 计算属性CSSOM树
  • 布局阶段Layout
  • 分层Layer
  • 绘制Paint
  • 分块
  • 光栅化和合成

图3 关键渲染路径步骤(几年前的渲染步骤) 【浏览器】Chrome浏览器的执行机制(内附相关知识点面经串联)

注意:parse HTML 和 parse CSS其实是同时进行的(非常重要!!!)

接下来详细分别阐述一下每个步骤,(我感觉整个过程是一场“维密秀”,怎么说呢,你听我慢慢瞎扯)

1 parseHTML 构建DOM树

  • 什么是DOM,为什么要构建DOM?如何查看DOM?

DOM全称为“文档对象模型”(Document Object Model)

 文档表示的就是整个的HTML网页文档(就刚才图1那一整个html文档内容)

 对象表示将网页中的每一个部分都转换为了一个对象。

 模型来表示对象之间的关系,这样方便我们获取对象

而浏览器无法直接理解和使用HTML,所以需要将HTML转换为浏览器能够理解的结构——DOM 树,

F12按下输入document就可以看到DOM

(打开就可以看到 DOM 和 HTML 内容几乎是一样的,但是和HTML 不同的是,DOM 是保存在内存中树状结构,可以通过JavaScript来查询或修改DOM)

也就是说:输入HTML文件 经过HTML解析器 输出DOM树

而由上图1可见浏览器拿到的HTML文档是很长的 不可能等解析完了再显示页面(会造成长时间的空白页),所以浏览器只要拿到一部分就开始构建DOM,构建DOM树的过程如下图4所示:

图4:DOM树的构建过程 【浏览器】Chrome浏览器的执行机制(内附相关知识点面经串联) 在网络中传输的都是二进制01代码Bytes

通过指定解析方法(如UTF-8等)得到characters(html的head中有一行<meta charset="UTF-8"/>

这些字符集会由Tokenier分成一个个的Tokens,如图5所示

拆分后的Tokens就会变成一个个的结点Nodeds ,最后根据tokens解析的包含嵌套关系生成一棵类似于树状图的DOM树

页面的呈现就相当于是一场维密秀,是离不开台前和幕后的准备的,body里的就是台前,观众可以看到的舞台呈现内容,离不开幕后head里工作人员的准备工作。

按照浏览器的执行顺序,是先处理head中的内容,也就是先做宣传准备工作(head中的标签如:meta,link,script,style,title),才会保证秀body的最终正常展示

图5:Tokenizer解析出Tokens(不同于网络中的令牌token) 【浏览器】Chrome浏览器的执行机制(内附相关知识点面经串联)

八股文之

  • 对meta标签的了解
  • html语义化标签(对语义化的理解)?
  • <!doctype html>? 进一步问html5新特性

2 计算属性 构建styleSheets(CSSOM)

现在我们已经生成 DOM 树了,但是 DOM 节点的样式我们依然不知道,要让 DOM 节点拥有正确的样式,这就需要样式计算了(严格来讲这个地方不应该是2,因为是和1同时进行的)

和 HTML 文件一样,浏览器也是无法直接理解这些纯文本的 CSS 样式,所以当渲染引擎接收到 CSS 文本时,会执行一个转换操作,将 CSS 文本转换为浏览器可以理解的结构——styleSheets(F12输入document.styleSheets就可以看到),该结构同样具备了查询和修改功能,这会为后面的样式操作提供基础(可以理解为化妆师JS给模特后台补妆),构建CSSOM的过程如下图6所示

图6:构建CSSOM的过程(其实还存在转换样式表中的属性值,使其标准化的阶段) 【浏览器】Chrome浏览器的执行机制(内附相关知识点面经串联)

注意: 得到了styleSheets之后我们不是马上就应用在DOM树上了,如2em、blue、bold,这些类型数值不容易被渲染引擎理解,所以我们转换样式表中的属性值,使其标准化,如下图7所示 【浏览器】Chrome浏览器的执行机制(内附相关知识点面经串联)

现在样式的属性已被标准化了,接下来就需要计算 DOM 树中每个节点的样式属性了,如何计算呢?这就涉及到 CSS 的继承规则和层叠规则了。 【浏览器】Chrome浏览器的执行机制(内附相关知识点面经串联)

也就是说CSSOM构建的整个过程是:

输入css文件 ---> 经过css解析器整理成styleSheets --根据css的层叠和继承性--> 输出每个 DOM 节点的样式,并被保存在 ComputedStyle 的结构内 ---> CSSOM

不同于DOM的构建是一个循序渐进的过程,因为CSS的样式存在覆盖性,会以最终结果为准,如果我们提前构建就会出错

在有了DOM树后相当于模特选角就有了模特是可以一个接一个的走出来(避免空白页面冷场,DOM的构建是循序渐进的)但她们的衣服(CSSOM)一定都是幕后工作人员head提前全部准备好了的(完整的CSS文件)

(所以感觉从这里可以看出CSS加载的优先级蛮高的,一般通过link放在head中提前加载完成)

css样式文件的引入有三种方式

  • 通过link引用的外部 CSS 文件
  • <style>标记内的 CSS
  • 元素的 style 属性内联的 CSS

没有样式或者内联样式--> css的解析就在parse HTML过程中

外部样式 --> css的解析就在parse CSS过程中

八股文之css选择器权重?link和@import导入样式的区别? HTML中href、src 区别

3 布局阶段Layout

截至目前我们已经有了DOM树和结点样式styleSheet(或者叫CSSOM?我看有些博客说可以等价,期待一位大佬在评论区解答一下),那么接下来就需要计算出 DOM 树中可见元素的几何位置,我们把这个计算过程叫做布局

注:要是修改了元素的几何属性(如宽、高、边距),就会从这个阶段重新执行下面的所有流程,这个过程叫做重排

Chrome 在布局阶段需要完成两个任务:创建布局树布局计算

3.1创建布局树

【浏览器】Chrome浏览器的执行机制(内附相关知识点面经串联)

不是所有人都上场,而是只有模特(“可见”)才会走上t台而幕后人员并不上台(head,display:none),替补可能上场(visibility:hidden)

八股文之:display相关属性? display:none和visibility:hidden、opacity: 0的区别? opacity和rgba的区别?

所以布局树的构建过程是

  1. 浏览器从DOM开始 遍历每一个“可见”结点
  2. 对于每一个“可见”结点,在CSSOM上找到匹配的样式并引用每个模特有自己对应的服装
  3. 上面两者对应相结合 生成布局树,如下图所示 【浏览器】Chrome浏览器的执行机制(内附相关知识点面经串联)

现在我们有了一棵完整的布局树(任务一完成,创建布局树)。那么接下来,就要计算布局树节点的坐标位置了(任务二:布局计算)。在执行布局计算的时候,会把布局运算的结果重新写回布局树中

这个地方再复习一下:上面的CSS加载为什么重要

因为布局树依赖于DOM树和CSSOM树,所以必须等到CSSOM树构建完成,也就是CSS资源加载完成

八股文之:CSS的匹配规则是从右往左的 就是为了页面尽快的渲染

但其实MDN中也指出,”在 CSS 中选择器的性能优化,提升仅仅是毫秒级的。有其他一些方式来优化 CSS,例如压缩和使用媒体查询来异步处理 CSS 为非阻塞的请求“

考虑如下场景:此时构建了部分DOM,而CSSOM构建是完全完成的,浏览器就会开始构建Render Tree,如果我们找到一条规则从右往左的匹配,我们就只需要逐层观察该节点的父节点是否匹配,而此时的父节点肯定已经在DOM上了,但是反过来我们可能匹配到一个还未出现在DOM上的结点 (ps:想到了LeetCode上的一道题另一棵树的子树 DOM树就是那一颗子树,而CSSOM就是一颗完整的树,要把DOM子树和CSSOM树匹配起来最快该怎么匹配)

3.2 布局计算

布局树构建了之后就知道了页面需要挂载哪些元素,以及挂载元素的样式

接下来就需要知道挂载在哪,也就是计算出相对于视窗(屏幕)的位置和大小

引出CSS盒子模型,每个盒子摆在哪 怎么摆的问题 模特要怎么走,站定的posing是啥

八股文之 css定位属性position? 如何脱离文档流? 常见布局方式(flex,grid,双飞翼,圣杯布局)

4 分层Layer

为什么要分层? 因为页面可能存在3D变换,页面滚动或z-indexing做z轴排序等效果,为了更加方便地实现这些效果,渲染引擎还需要为特定的节点生成专用的图层,并生成一棵对应的图层树,而这些图层叠加在一起才形成了最终的页面

面试八股之:z-index压盖顺序? 过渡与动画?

那图层树(LayerTree)和布局树(LayoutTree)的关系是什么呢? 如果布局树中的某个节点没有对应的图层树,那它就从属于父节点的图层树(有点像对象通过原型链查找属性或方法的概念,只不过这个地方是节点查找自己所从属的图层) 布局树中每一个节点都会直接或者间接地从属于一个层 【浏览器】Chrome浏览器的执行机制(内附相关知识点面经串联) 那满足什么条件可以被单独赋予一个图层呢?

if(拥有层叠上下文属性的元素 || 需要剪裁) { 会为单独的一层 } 什么是层叠上下文?

5 图层绘制

以下括号内的内容是自己的理解哈

在完成图层树(LayerTree)的构建后,就开始依次对每个图层(for Layer of LayerTree)进行绘制,而每个图层(for nodes of Layer)也拆分成一步一步的绘制指令放到绘制列表里等待执行

注:如果修改了元素的背景颜色,就会从这个阶段重新执行下面的所有流程,这个过程叫做重绘 相较于重排开销要小得多,因为省去了布局和分层阶段

面试八股文之 用CSS画一个三角形? 怎么画宽度为0.5px的线?

6 栅格化操作

浏览器主线程会将绘制列表中的操作指令给到(commit)浏览器的渲染进程中的合成线程来完成

注: 当前的浏览器为多进程架构,最新的 Chrome 浏览器包括:1 个浏览器(Browser)主进程、1 个 GPU 进程、1 个网络(NetWork)进程、多个渲染进程和多个插件进程他们各自的工作是什么,是如何分工合作的? 每个进程中管理了哪些线程?(遇到疑问先加粗,挖个坑到时候写了放链接)

合成线程会将先图层划分为图块(256x256 或者 512x512),因为有的图层很大,而视窗(屏幕)可能很小,我们只需要加载视窗附近的区域,也就能避免绘制用户暂时看不到的区域造成额外开销

视窗附近区域所涉及到的图块会由合成线程生成位图,而合成线程也像主线程给它下放任务一样,将图块转换成位图的需求任务下放给栅格化线程。所谓栅格化,是指将图块转换为位图,而图块是栅格化执行的最小单位。渲染进程维护了一个栅格化的线程池,所有的图块栅格化都是在线程池内执行的 (除GPU生成位图时的快速栅格化外)

7 合成和显示

一旦所有图块都被光栅化,合成线程就会生成一个绘制图块的命令——“DrawQuad”

然后将该命令提交给浏览器进程。浏览器进程接收到合成线程发过来的 DrawQuad 命令

然后根据 DrawQuad 命令,将其页面内容绘制到内存中,最后再将内存显示在屏幕上。

注:如果实现动画,那么最小的消耗就是采用CSS的transform,这样会从该阶段重新开始,叫做合成

通过浏览器的执行机制,我们就知道了,为什么说我们要尽量减少对DOM的直接操作,因为一旦操作DOM这样所需要重新经历的流程就多了(Vue使用的虚拟DOM技术我好像有点懂了)

总结

首先会同步,html构建DOM树, CSS文件构建CSSOM树

在CSSOM树构建完成之后(层叠性),就往DOM树上匹配,形成渲染树RenderTree

渲染树对”可见节点“形成,计算布局,形成布局树LayoutTree

由于一些3D效果,布局树需要分层渲染,所以会形成图层树LayerTree

图层树最后进行栅格化以及合成 最后显示在屏幕上Painting

阻塞

好了 了解完浏览器的渲染流程后

是不是发现还没出现js的身影? 不要急,因为一开始浏览器就是类似于“电子报纸”的形式,只能阅读html和css写出来的静态页面,但不能交互,后来才出现了与浏览器互动的桥梁——JavaScript

程序媛通过js和浏览器提供的DOMAPIDOMAPI能够和页面产生一个交互(--->jQuery的出现)

(因为我个人会觉得这个背景挺重要的,知其所以然,因为既然JS的出现是为了操作页面,一般提到操作可以总结成“增 删 改”这类的词嘛,那对于DOM来讲能改变页面结构,对于CSSOM来讲能改变页面样式。)

下一坑:浏览器中JS的执行机制

参考文章和视频:

浏览器的执行机制和渲染机制

浏览器渲染经典文章(英语)

写的不错的文章

讲的不错的视频1

讲的不错的视频2

强烈推荐李兵老师的浏览器工作原理与实践 受益匪浅~