这是我参与8月更文挑战的第30天,活动详情查看:8月更文挑战
书接上回,在浏览器进程开始向渲染进程源源不断发送数据时,渲染进程开始工作。
渲染进程的关键路径
如果说导航进程的性能取决于网络的话,那么渲染进行的性能则取决于:渲染进程的工作流程+页面内容的多少。
渲染进程的工作流程被称为关键渲染路径:Critical Rendering Path,和项目管理中的关键路径法一样,它描述了整个渲染过程的关键路径,如果能缩短关键路径的执行时间,则整个渲染过程的性能就会得到优化。
简要说明一下关键渲染路径:渲染进程会解析HTML文件,并下载解析其中的css和script,生成结构化数据DOM TREE和CSSOM TREE,基于这两个输入,计算要呈现在页面上的渲染树Rander tree, 也叫样式树Style tree,有了具体的样式,还需要每个元素的具体坐标,这就要计算布局Layout,之后还需要确认绘制顺序,并对页面进行分层,这是绘画paint的输出,最后将各个图层进行栅格化,并合成为图像帧,发送给GPU进程输出页面,当然之后还会根据页面交互不停的重复以上步骤。
DOM解析
DOM(Document Object Module)文档对象模型,它是对HTML文档的结构化表述,可以让代码理解和使用的结构,能够使用如JavaScript等脚本语言对其进行操作,把web页面和编程语言联系了起来。
下面这张图就形象化的表示了浏览器从收到服务器响应数据后,将HTML文件解析成DOM对象的过程:
这其中有两个比较重要的过程,一个是词法分析(lexical analysis)和语法分析(Syntax analysis):
-
词法分析:是将输入的字符,分解成一个个有效token,这个过程也被称为Tokenization,这里的token不是令牌的意思,而是标记的意思,包括开始符号如<body>,结束符号</body>,属性名称,属性值等;
-
语法分析:将标记按照HTML语言的语法规则分析文档的结构,从而构建解析树,这里的解析树就是DOM tree
CSSOM解析
在浏览器解析HTML的同时,也会解析外部 CSS 文件以及样式元素中的样式数据,生成CSSOM (CSS Object Module)
- CSSOM数据同样是结构化的样式数据,可以供编程语言进行操作;
- 解析的流程是一样的,方法略有不同,因为CSS的语法和HTML不一样;
-
解析和构造CSSOM与解析DOM是可以并行的;
-
但下载和解析CSSOM会阻塞JavaScript的执行,因为JavaScript经常会用于查询元素的CSS样式信息。
预加载扫描器Preload scanner
-
在解析HTML文件时,如果遇到JS script则可能会导致HTML解析暂停,而先下载并执行script;
-
这是因为JavaScript可能会改变HTML文档的结构,从而导致DOM tree发生改变,所以必须等JavaScript执行完成之后才能继续对HTML文档流的解析;
-
为了能尽量缩短等待时间,一些浏览器会采用预加载扫描器的功能,就是在解析HTML的同时,会提前搜索外部引用的内容,并提前下载,这样当解析器解析到他们的位置时,资源已经准备好了;
-
另外,开发人员还可以在脚本标签上增加async 或 defer 属性,告知渲染进程这个脚本可以在解析完成后再执行,这样也可以提升页面渲染性能;
计算渲染树Render Tree
渲染进程会结合DOM和CSSOM,计算要在页面上呈现的渲染树:
-
这个渲染树上的节点只包括可见节点visible,那些不会出现在页面上的节点,比如<html>,<body>,不会出现在渲染树上;
-
渲染进程会遍历DOM上的每一个节点,再将可见的节点对应的属性匹配到这个节点上;
-
这里要注意,渲染树上的节点和DOM上的节点并不是一一对应的,有一些DOM节点可能对应多个渲染树节点,比如多行文本;
-
生成的渲染树,会用来供下一步计算每个节点的具体布局位置;
计算布局Layout
在创建完成渲染树后,这里面并没有节点的位置和大小信息,计算位置信息的过程称为布局,也可以叫重排(reflow)。
-
计算布局的方式是盒子模型(box model),浏览器把页面对象都看作一个个盒子,并计算他们的尺寸,计算的依据是屏幕的尺寸;
-
布局是一个递归的过程,渲染进程会遍历渲染树,并从根节点开始,递归遍历整个页面架构,从而进算出每个节点的具体位置;
绘制Paint
绘制也可以说是一个光栅化(rasterizing)的过程,将布局最终转化为屏幕上的像素:
-
光栅化即将屏幕分块,确定每个块中的元素具体样式;
-
在绘制的过程中,还会将layout分解成多个层layer,以此来决定绘制的顺序;
-
光栅化线程会光栅化每一层,然后将信息储存在GPU的内存中;
合成Compositing
合成线程是将上一步光栅化的层,按照不同优先级和清晰度,进行组合,构建一个合成帧(compositor frame)。
-
优先级是根据浏览器的窗口位置,在展示窗口内的,或者靠近展示窗口的,会被优先合成;
-
还可以根据用户对页面的放大缩小操作,合成不同清晰度的图块;
-
上面的步骤完成之后,渲染进程就会通过IPC向浏览器进程(browser process)提交(commit)一个合成帧compositor frame;
-
合成帧都会被发送给GPU从而展示在屏幕上。如果浏览器监听到页面滚动事件,就会通知渲染进程构建另外一个合成帧来更新页面;
以上就是浏览器的整个关键渲染路径的描述,感谢阅读,如有不准确和错误之处请留言指正,我会立即修正,感谢!
总结不易,请勿私自转载,否则别怪老大爷不客气
欢迎喜欢技术的小伙伴和我交流,微信1296386616
参考资料:
《Inside look at modern web browser》 By Mariko Kosaka developers.google.com/web/updates…
《How Browsers Work: Behind the scenes of modern web browsers》 By Tali Garsiel and Paul Irish www.html5rocks.com/zh/tutorial…
《Critical Rendering Path 》 Ilya Grigorik developers.google.com/web/fundame…
《Populating the page: how browsers work》 MDN developer.mozilla.org/zh-CN/docs/…
《网页性能管理详解》 阮一峰 www.ruanyifeng.com/blog/2015/0…
《前端都该懂的浏览器工作原理,你懂了吗?》 _杨溜溜 segmentfault.com/a/119000002…
《一文看懂Chrome浏览器工作原理》 进击的大葱 juejin.cn/post/684490…