浏览器的秘密 (2) 关键渲染路径

357 阅读6分钟

这是我参与8月更文挑战的第30天,活动详情查看:8月更文挑战

书接上回,在浏览器进程开始向渲染进程源源不断发送数据时,渲染进程开始工作。

渲染进程的关键路径

如果说导航进程的性能取决于网络的话,那么渲染进行的性能则取决于:渲染进程的工作流程+页面内容的多少。

渲染进程的工作流程被称为关键渲染路径:Critical Rendering Path,和项目管理中的关键路径法一样,它描述了整个渲染过程的关键路径,如果能缩短关键路径的执行时间,则整个渲染过程的性能就会得到优化。

未命名文件(5).png

简要说明一下关键渲染路径:渲染进程会解析HTML文件,并下载解析其中的css和script,生成结构化数据DOM TREE和CSSOM TREE,基于这两个输入,计算要呈现在页面上的渲染树Rander tree, 也叫样式树Style tree,有了具体的样式,还需要每个元素的具体坐标,这就要计算布局Layout,之后还需要确认绘制顺序,并对页面进行分层,这是绘画paint的输出,最后将各个图层进行栅格化,并合成为图像帧,发送给GPU进程输出页面,当然之后还会根据页面交互不停的重复以上步骤。

DOM解析

DOM(Document Object Module)文档对象模型,它是对HTML文档的结构化表述,可以让代码理解和使用的结构,能够使用如JavaScript等脚本语言对其进行操作,把web页面和编程语言联系了起来。

下面这张图就形象化的表示了浏览器从收到服务器响应数据后,将HTML文件解析成DOM对象的过程:

image.png

这其中有两个比较重要的过程,一个是词法分析(lexical analysis)和语法分析(Syntax analysis):

  • 词法分析:是将输入的字符,分解成一个个有效token,这个过程也被称为Tokenization,这里的token不是令牌的意思,而是标记的意思,包括开始符号如<body>,结束符号</body>,属性名称,属性值等;

  • 语法分析:将标记按照HTML语言的语法规则分析文档的结构,从而构建解析树,这里的解析树就是DOM tree

CSSOM解析

在浏览器解析HTML的同时,也会解析外部 CSS 文件以及样式元素中的样式数据,生成CSSOM (CSS Object Module)

  • CSSOM数据同样是结构化的样式数据,可以供编程语言进行操作;
  • 解析的流程是一样的,方法略有不同,因为CSS的语法和HTML不一样;

image.png

  • 解析和构造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,计算要在页面上呈现的渲染树:

image.png

  • 这个渲染树上的节点只包括可见节点visible,那些不会出现在页面上的节点,比如<html>,<body>,不会出现在渲染树上;

  • 渲染进程会遍历DOM上的每一个节点,再将可见的节点对应的属性匹配到这个节点上;

  • 这里要注意,渲染树上的节点和DOM上的节点并不是一一对应的,有一些DOM节点可能对应多个渲染树节点,比如多行文本;

  • 生成的渲染树,会用来供下一步计算每个节点的具体布局位置;

计算布局Layout

在创建完成渲染树后,这里面并没有节点的位置和大小信息,计算位置信息的过程称为布局,也可以叫重排(reflow)。

  • 计算布局的方式是盒子模型(box model),浏览器把页面对象都看作一个个盒子,并计算他们的尺寸,计算的依据是屏幕的尺寸;

  • 布局是一个递归的过程,渲染进程会遍历渲染树,并从根节点开始,递归遍历整个页面架构,从而进算出每个节点的具体位置;

image.png

绘制Paint

绘制也可以说是一个光栅化(rasterizing)的过程,将布局最终转化为屏幕上的像素:

  • 光栅化即将屏幕分块,确定每个块中的元素具体样式;

  • 在绘制的过程中,还会将layout分解成多个层layer,以此来决定绘制的顺序;

  • 光栅化线程会光栅化每一层,然后将信息储存在GPU的内存中;

image.png

合成Compositing

合成线程是将上一步光栅化的层,按照不同优先级和清晰度,进行组合,构建一个合成帧(compositor frame)。

image.png

  • 优先级是根据浏览器的窗口位置,在展示窗口内的,或者靠近展示窗口的,会被优先合成;

  • 还可以根据用户对页面的放大缩小操作,合成不同清晰度的图块;

  • 上面的步骤完成之后,渲染进程就会通过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…