浏览器渲染流程

浏览器的进化过程

  • 1990年,蒂姆·伯纳斯·李开发了第一个网页浏览器WorldWideWeb,后改名为Nexus。WorldWideWeb浏览器支持早期的HTML标记 语言,功能比较简单,只能支持文本、简单的样式表、电影、声音、图片等资源的显示。

  • 1993年,马克·安德森领导的团开发了一个真正有影响力的浏览器Mosaic,这就是后来世界上最流行的浏览器Netscape Navigator。

  • 1998年,Netscape公司开放Netscape Navigator源代码,成立了Mozilla基金会。第二次浏览器大战开始,持续八年 🏃‍♀️

  • 2003年,苹果公司发布了Safari浏览器。

  • 2004年,Netscape公司发布了著名的开源浏览器Mozilla Firefox

  • 2005年,苹果公司开源了浏览器中的核心代码,基于此发起了一个新的开源项目WebKit(Safari浏览器的内核)。

  • 2008年,Google公司已WebKit为内核,创建了一个新的浏览器项目Chromium。以Chromium为基础,谷歌发布了Chrome浏览器。 至于这两者的关系,可以简单地理解为:Chromium为实验版,具有众多新特。。Chrome为稳定版。

现在浏览器特征与架构

  • 网络 最初的浏览器只有上网功能。
    现在浏览器网络是基本特征,网络不仅仅支持http协议,还支持ftp协议等多种网络协议。

  • 资源管理 资源管理最重要的就是缓存机制,从ie开始出现了缓存机制。

  • 网页浏览

  • 多页面管理 早期的浏览器是打开新的窗口,现在的浏览器是打开tab页。
    ie5的时候开始推出,但是当时的谷歌和ie浏览器实现的多页面管理机制还不一样。
    ie5的多页面管理是多线程维护。
    谷歌的浏览器是基于进程,一个域对应一个进程。

  • 插件和扩展 实际上是增强浏览器功能的,是基于js引擎的

  • 账户和同步 最早出现账户和同步的是火狐

  • 安全机制 安全机制是现代浏览器非常重要的特征,比如说跨域什么的,防止出现安全漏洞。
    浏览器还会提供沙箱环境,安全性就更高了。
    安全机制是现代浏览器最重要的部分,可以保护用户的安全隐私等。。。

  • 开发者工具 帮助开发者调试网页

现代浏览器结构

client

把浏览器看成系统的话,里面有八个子系统:

  • 用户界面(User Interface)
  • 浏览器引擎(Browser Engine)
  • 渲染引擎(Rendering Engine)
  • 网络(Networking)
  • XML解析器(XML Parser)
  • 显示后端(Display Backend)
  • 数据持久层(Data Persistence)软件在设计的过程中都是按层次进行设计的,整个系统更有条理。

浏览器引擎能够加载url,还管着前进后退刷新等等,还提供各种各样的hook,看网页的加载速度。

渲染引擎是浏览器的核心,使页面可视化,还可以处理html和xml(结构化文档,HTML的一个全集)。

最早的html并没有严格按照xml的规范制定,微软为了扩大竞争力,对有问题的页面做了兼容处理,尽可能的让页面正常显示。 一直到html5,html语法才重新被规范起来,最早的xml用的非常广泛,但是太重,解析的时候很消耗资源。

xml 解析方式

  • DOM解析 完全按照节点的结构,然后把它在内存中生成DOM树。这种方式对内存消耗比较多,解析速度慢

  • SAX解析 根据语义解析,类似于处理文本,不生成dom,速度快,但是对xml的处理太简单,不能满足更加复杂的需求。

css也在渲染引擎里面,嵌入页面的图片图标什么的也都在渲染引擎里面去做。
页面的排版也在渲染引擎里面。
渲染引擎里面包含的是html解析器,xml解析器不在渲染引擎里面。

网络支持http,ftp等协议,还可以支持字符集切换。
js解释器,最熟悉的应该就是谷歌的v8了。
显示后端是在界面上提供一些绘图和窗口的基本操作和支持,比如说userinterface,各种各样的字体等等。 数据持久层,是做缓存的,除了缓存之外,还有cookie,证书,用户系统配置等。

常用的渲染引擎

渲染引擎:能够能够将HTML/CSS/JavaScript文本及相应的资源文件转换成图像结果

渲染引擎浏览器
TridentIE,Edge(旧)
Geckofirefox
webkitsafari
blink(webkit fork)chromium/chrome,opera,edge(新)

Trident已经没了,不是微软自己的东西。 火狐的Gecko市场占有率很低了,感觉快完了。

webkit是safari一直在用的。

chrome的渲染引擎是基于webkit的,属于webkit的一个分支。但是好多东西已经替换了。

渲染引擎结构与工作流程

以html/javascript/css 等文件作为输入,以可视化内容为输出。现在可能会加上wasm。

一般来说内部渲染我们不关心,但是为了性能优化,必须得知道它干了什么。里面分为了四个步骤:

  • Parsing HTML to construct DOM Tree

    先把html初始化为dom树(HTML)。

  • Render Tree Construction 生成渲染树(css)。

  • Layout of Render Tree

    排版规则,对渲染树进行布局,要把样式应用到dom树上去。

  • Painting Render Tree

    绘制,把你的页面渲染出来,调用渲染后端。

client-render

chrome 浏览器架构

performance-chorme
  • Browser: 控制程序的"chrome"部分,包括地 址栏,书签,后退和前进按钮。还处理Web浏览器的不可见的,和特权部分,例如网络请求和文件访问。

  • Renderer: 负责显示网站的选项卡内的所有内容。

  • Plugin: 控制网站使用的所有插件,例如 flash。

  • GPU: 独立于其他进程的GPU处理任务。它被分成多个不同的进程,因为GPU处理来自多个程序的请求并将它们绘制在同一个面中。

chrome是一个多进程的架构, 相同域跑在同一个进程里面。浏览器里面的很多东西都服务化了,早期全都是独立的进程,后来合并到线程上去了,减少了内存的消耗。

chrome 渲染器进程

渲染器进程负责选项卡内发生的所有事情。在渲染器进程中,主线程处理你为用户编写的大部分代码。

如果你使用了 webworker 或者 serviceworker,有时JavaScript代码的一部分将由工作线程处理。排版和栅格线程也在渲染器进程内运行。以便高效,流畅地呈现页面。

chrome-renderer-process

渲染过程-> 解析部分

首先html 进来是个文本,要先把它给转化成 dom=> 生成 dom 树。 再进行 dom 渲染的过程中,如果说文档里面有引用的资源(脚本,图片,css),会继续向网络线程发请求(并行)。

这个过程叫子资源加载主资源是文档的本身。

在这个步骤中,会逐行的扫描,一边扫描一边生成。扫描到脚本的时候生成 dom 树的过程会暂停,要把这个脚本拿过来(js可能会要操作 dom)。

css可以靠后,在渲染树的时候才要用到 css。

在生成 dom 树之后,就要处理样式表了,拿到样式表之后对它进行处理计算。它把样式表当中定义的样式和 dom 元素做一个关联,这个过程就叫做计算样式表。这个步骤也是在主线程完成的。计算完之后生成了渲染树。

渲染树生成完了,就该布局了。布局处理的模块要根据样式描述的规则在绘制的过程中按照生成的规则绘制。

  • 首先构建 dom
  • 子资源加载(JavaScript可以阻止解析)
  • 提示浏览器如何加载资源
  • 样式表计算
  • 布局
  • 绘制
build_process

渲染过程 -> 合成部分

把绘制过程的描述变成像素点,一个个点效率很低,所以有一套转换规则=>光栅化

  • 把文档的结构,元素的样式,集合形状和绘制顺序转换为屏幕上的像素称为光栅化。
  • 合成是一种将页面的各个部分分层,分别栅格化,并在一个被成为合成器线程的独立线程中合成为页面的技术。
build_layout

渲染过程 -> GPU 渲染

GPU 在工作的时候并不会把整个页面一次性处理完,会把页面划分成若干个块(tile),gpu 在处理的时候一块块的进行处理。

CPU 是通用型处理器,什么都能干,但是在某些事情效率不高,最擅长的事情是做整数运算。

而在处理图形的时候都是浮点运算,此时轮到 gpu 上场。

GPU是一个众核处理器(起码得超过 48 个),每个核心功能单一,流程简单。

就是因为 gpu 是众核处理器,核心非常多,运算任务分配到每一个核心,所以渲染速度非常快。

GPU渲染在独立的进程里面,不会干扰主进程,尤其是不会和处理 js 任务冲突。

  • 一旦创建了层树并确定了绘制顺序,主线程就会将该信息提交给合成器线程。合成器线程然后栅格化每个图层。一个图层可能像页面的整个长度一样大,因此合成器线程会将它们分成土块,并将每个图块发送到光栅线程。栅格线程栅格化每一个 tile 并将它们存储在 gpu 内存中。

  • 通过 IPC 将合成器帧提交给浏览器进程。这时可以从 ui 线程添加另一个合成器帧以用于浏览器 ui 更改,或者从其他渲染器进程添加扩充数据。这些合成器帧呗发送到 gpu 用来在屏幕上显示。如果发生滚动时间,合成器线程会创建另一个合成器帧并发送到 gpu。

  • 合成的好处是它可以在不涉及主线程的情况下完成。合成线程不需要等待样式计算或 JavaScript 执行。这就是合成动画是平滑性能的最佳选择的原因。如果需要再次计算布局或绘图,则必须涉及主线程。

初窥webkit

performance

👉👉👉 webkit 官网open in new window

👉👉👉 Blink是未来,官方文档open in new window

Last Updated:
Contributors: kk