浏览器是如何渲染网页的

现在我们主要接触的主流浏览器有:IE, FireFox, Safari, Chrome,Opera;
你真的了解它们吗?

1. 浏览器的主要功能
  • 向服务器发出请求,在浏览器窗口中展示你选择的网络资源;(一般指 HTML 文档,也可以是 PDF,图片,或其他的类型)资源的位置由用户使用的 URL(统一资源标示符)指定。
    浏览器解释并显示 HTML 文件的方式是在 HTML 和 CSS 规范中指定的。这些规范由网络标准化组织 W3C(万维网联盟)进行规定。
2. 浏览器的主要组件

浏览器的主要组件

  • 用户界面:(包括地址栏,前进/后退按钮,书签菜单等)。除了浏览器主窗口显示的各个部分都属于用户界面
  • 浏览器引擎:在用户界面和呈现引擎之间传送指令
  • 呈现引擎/渲染引擎/浏览器内核/排版引擎/解释引擎:负责显示请求的内容,并将解析后的内容显示在浏览器屏幕上
  • 网络:用于网络调用,比如 HTTP 请求,其接口与平台无关,并为所有平台提供底层实现。
  • 用户界面的后端:用于绘制基本的窗口小部件,比如组合框和窗口。其公开了与平台无关的通用接口,而在底层
    使用操作系统的用户界面方法。
  • JavaScript 解释器:用于解析和执行 JavaScript 代码
1
2
3
4
5
6
主流浏览器	js引擎
IE -> Edge JScript(IE3.0-IE8.0) / Chakra
Chrome V8(大名鼎鼎)
Safari Nitro(4-)
Firefox SpiderMonkey(1.0-3.0)/ TraceMonkey(3.5-3.6)
Opera Linear A(4.0-6.1)/ Linear B(7.0-9.2)
  • 数据存储:(持久层);浏览器需要在硬盘上保存各种数据,例如 Cookie。HTML5 定义了”网络数据库“(完整且轻便的浏览器内数据库)
3. 渲染引擎/浏览器内核解析
  • 默认情况下,呈现引擎可显示 HTML 和 XML 文档与图片,通过插件(或浏览器扩展程序)显示,eg:PDF 查看器插件就可以显示 PDF 文档。
  • 不同的浏览器浏览器内核不相同
1
2
3
4
5
6
主流浏览器	内核
IE -> Edge trident->EdgeHTML
Chrome webkit->blink
Safari webkit
Firefox Gecko
Opera Presto->blink
4.浏览器渲染基本流程
1
2
3
4
从网络层获取请求文档的内容(内容的大小一般限制在8000个块以内)--->
解析HTML构造DOM树和CSSOM树--->构建渲染树(把DOM树中的一些不可视元素去掉,
然后与CSSOM合成一棵render树)--->渲染DOM树布局(计算出各个节点(元素)在屏幕的位置)
-->渲染树绘制(浏览器根据渲染树将页面渲染到屏幕)

浏览器渲染流程

(1). 解析 HTML 文档一边边构建 DOM 树一边构建 CSS 规则树(CSSOM)
  • 解析 HTML/XHTML 文档时,将各标记逐个转化成”内容树”上的 DOM 节点,遇到 css 标签或 JS 脚本标签就下载和解析(其中 css 是异步下载同步执行);
  • 在构建 DOM 树过程中,当遇到 css 元素{包括外部 CSS 样式以及内联样式},浏览器会开启一个异步请求线程,在该线程上,浏览器会去请求相应的 css 文件,并且根据该文件去构建 CSSOM 树(也叫 css rule),css 的加载并不会导致 html 解析和渲染的停止,即不会阻塞 dom 树的构建;该线程会阻塞 JavaScript 引擎线程(即 css 后 面的 js 模块的解析会在 css 解析完毕后执行),因为 js 脚本不仅可以读取修改到 dom,也可以读取修改到 cssom。故在 js 脚本执前,browser 必须保证到 css 文件完全加载并解析完成,即 cssom 树完全构建好。这就导致了 js 执行的延迟,也因此导致 html 解析和渲染延迟。(这就是 css 阻塞 js 执行,阻塞渲染的根本原因)

  • 构建 DOM 树过程中,浏览器渲染和 JS 执行是共用一个线程,即单线程工作,多线程会产生渲染 DOM 冲突。如果遇到当遇到 JS 元素时,HTML 解析器就会将控制权转让给 JavaScript 引擎线程,该线程会阻断 HTML 解析器的运行,就阻塞了 DOM 树的构建
    当 js 加载并且执行完毕后,JavaScript 引擎线程会将控制权还给 HTML 解析器,让其去继续构建 dom 树。也就是说,如果你想首屏渲染的越快,就越不应该在首屏就加载 JS 文件,这也是都建议将 script 标签放在 body 标签底部的原因。当然,并不是说 script 标签必须放在底部,因为你可以给 script 标签添加 defer 或者 async 属性

  • JS 文件不只是阻塞 DOM 的构建,它会导致 CSSOM 也阻塞 DOM 的构建。原本 DOM 和 CSSOM 的构建是互不影响,井水不犯河水,但是一旦引入了 JavaScript,CSSOM 也开始阻塞 DOM 的构建,只有 CSSOM 构建完毕后,再恢复 DOM 树构建。这是因为JavaScript 不只是可以改 DOM,它还可以更改样式,也就是它可以更改 CSSOM。因为不完整 CSSOM 是无法使用的,如果 JavaScript 想访问 CSSOM 并更改它,那么在执行 JavaScript 时,必须要能拿到完整的 CSSOM。所以就导致了一个现象,如果浏览器尚未完成 CSSOM 的下载和构建,而我们却想在此时运行脚本,那么浏览器将延迟脚本执行和 DOM 构建,直至其完成 CSSOM 的下载和构建。也就是说,在这种情况下,浏览器会先下载和构建 CSSOM,然后再执行 JavaScript,最后在继续构建 DOM。

  • CSS 规则树中的元素是和 DOM 元素相对应的,但并非一一对应。非可视化的 DOM 元素不会插入规则树中,例如“head”元素。如果元素的 display 属性值为“none”,那么也不会显示在规则树中(但是 visibility 属性值为“hidden”的元素仍会显示)。有一些 DOM 元素对应多个可视化对象。它们往往是具有复杂结构的元素,无法用单一的矩形来描述。

eg:DOM 树

DOM树

eg:CSSOM 树

CSSOM树

(2). 浏览器引擎通过 DOM 树和 CSS 规则树(CSSOM)生成一颗渲染树(Rendering Tree)
  • 渲染树是由 DOM 树和 CSSOM 树合成的;渲染树的每一个节点都有自己的 style 样式;渲染树上没有隐藏的节点,比如 display:block 和无样式 head 节点,就不会在渲染树上,因为这些节点不会呈现也不影响呈现;visibility:hidden 会存在渲染树,因为它占有空间,会影响布局)
    渲染树
(3). 渲染 DOM 树布局(reFlow 或 Layout)

通过 CSS 规则树 匹配 DOM 树每个节点分配一个应出现在屏幕上的确切坐标,即进行定位坐标和大小

(4). 绘制(paint)[调用操作系统 Native GUI 的 API 绘制]

呈现引擎会遍历呈现树,由用户界面后端层将每个节点绘制出来。

5.面试常问
  • 浏览器渲染原理解析/浏览器渲染过程/浏览器怎么加载页面的?浏览器如果渲染过程中遇到 CSS 文件/JS 文件怎么处理?/dom 树和 css 树是如何合并的?/浏览器的运行机制是什么/什么会造成渲染阻塞?如何优化
参考文章
浏览器运行机制参考文章

2019-05-05 18:42:17 星期日

-------------本文结束感谢您的阅读-------------