资讯专栏INFORMATION COLUMN

JavaScript是如何工作的:渲染引擎和优化其性能的技巧

big_cat / 2879人阅读

摘要:渲染树的布局创建渲染器并将其添加到树中时,它没有位置和大小,计算这些值称为布局。根渲染器的位置为,其尺寸与浏览器窗口的可见部分即的大小相同。渲染器使其在屏幕上的矩形无效,这会导致操作系统将其视为需要重新绘制并生成绘事件的区域。

这是专门探索 JavaScript 及其所构建的组件的系列文章的第11篇。

想阅读更多优质文章请猛戳GitHub博客,一年百来篇优质文章等着你!

如果你错过了前面的章节,可以在这里找到它们:

JavaScript 是如何工作的:引擎,运行时和调用堆栈的概述!

JavaScript 是如何工作的:深入V8引擎&编写优化代码的5个技巧!

JavaScript 是如何工作的:内存管理+如何处理4个常见的内存泄漏 !

JavaScript 是如何工作的:事件循环和异步编程的崛起+ 5种使用 async/await 更好地编码方式!

JavaScript 是如何工作的:深入探索 websocket 和HTTP/2与SSE +如何选择正确的路径!

JavaScript 是如何工作的:与 WebAssembly比较 及其使用场景 !

JavaScript 是如何工作的:Web Workers的构建块+ 5个使用他们的场景!

JavaScript 是如何工作的:Service Worker 的生命周期及使用场景!

JavaScript 是如何工作的:Web 推送通知的机制!

JavaScript是如何工作的:使用 MutationObserver 跟踪 DOM 的变化

当你构建 Web 应用程序时,你不只是编写多带带运行的 JavaScript 代码,你编写的 JavaScript 正在与环境进行交互。了解这种环境,它的工作原理以及它的组,这些有助于你够构建更好的应用程序,并为应用程序发布后可能出现的潜在问题做好充分准备。

浏览器的主要组件包括:

用户界面 (User interface): 包括地址栏、后退/前进按钮、书签目录等,也就是你所看到的除了用来显示你所请求页面的主窗口之外的其他部分

浏览器引擎 (Browser engine):用来查询及操作渲染引擎的接口

渲染引擎 (Rendering engine):用来显示请求的内容,例如,如果请求内容为 html,它负责解析 html 及 css,并将解析后的结果显示出来

网络 (Networking):用来完成网络调用,例如http请求,它具有平台无关的接口,可以在不同平台上工作

UI 后端 (UI backend):用来绘制类似组合选择框及对话框等基本组件,具有不特定于某个平台的通用接口,底层使用操作系统的用户接口

JS 解释器 (JavaScript engine):用来解释执行JS代码

数据存储 (Data persistence): 属于持久层,浏览器需要在硬盘中保存类似 cookie 的各种数据,HTML5定义了 Web Database 技术,这是一种轻量级完整的客户端存储技术,支持的存储机制类型包括 localStorage、indexDB、WebSQL和 FileSystem。

在这篇文章中,将重点讨论渲染引擎,因为它处理 HTML 和 CSS 的解析和可视化,这是大多数 JavaScript 应用程序经常与之交互的东西。

渲染引擎概述

渲染引擎的职责就是渲染,即在浏览器窗口中显示所请求的内容。

渲染引擎可以显示 HTML 和 XML 文档和图像。如果使用其他插件,渲染引擎还可以显示不同类型的文档,如 PDF。

渲染引擎 (Rendering engines)

与 JavaScript 引擎类似,不同的浏览器也使用不同的渲染引擎。以下是一些最受欢迎的:

Gecko — Firefox

WebKit — Safari

Blink — Chrome,Opera (版本 15 之后)

Firefox、Chrome 和 Safari 是基于两种渲染引擎构建的,Firefox 使用 Geoko——Mozilla 自主研发的渲染引擎,Safari 和 Chrome 都使用 Webkit。Blink 是 Chrome 基于 WebKit的自主渲染引擎。

渲染的过程

渲染引擎从网络层接收所请求文档的内容。

解析 HTML 以构建 Dom 树 -> 构建 Render 树 -> 布局 Render 树 -> 绘制 Render 树

构建 Dom 树

渲染现引擎的第一步是解析 HTML文档,并将解析后的元素转换为 DOM 树中的实际 DOM 节点。

假如有如下 Html 结构


  
    
    
  
  
    

Hello, friend!

Smiley face

对应的 DOM 树如下:

基本上,每个元素都表示为所有元素的父节点,这些元素直接包含在元素中。

构建 CSSOM

CSSOM 指的是 CSS 对象模型。 当浏览器构建页面的 DOM 时,它在 head 标签下如遇到了一个 link 标记且引用了外部 theme.css CSS 样式表。 浏览器预计可能需要该资源来呈现页面,它会立即发送请求。 假设 theme.css 文件内容如下:

body { 
  font-size: 16px;
}

p { 
  font-weight: bold; 
}

span { 
  color: red; 
}

p span { 
  display: none; 
}

img { 
  float: right; 
}

与 HTML一样,渲染引擎需要将 CSS 转换成浏览器可以使用的东西—— CSSOM。CSSOM 结构如下:

你想知道为什么 CSSOM 是一个树形结构? 在为页面上的任何对象计算最终样式集时,浏览器以适用于该节点的最常规规则开始(例如,如果它是 body 元素的子元素,则应用所有 body 样式),然后递归地细化,通过应用更具体的规则来计算样式。

来看看具体的例子。包含在 body 元素内的 span 标签中的任何文本的字体大小均为 16 像素,并且为红色。这些样式是从 body 元素继承而来的。 如果一个 span 元素是一个 p 元素的子元素,那么它的内容就不会被显示,因为它被应用了更具体的样式(display: none)。

另请注意,上面的树不是完整的 CSSOM 树,只显示我们决定在样式表中覆盖的样式。 每个浏览器都提供一组默认样式,也称为“user agent stylesheet”。这是我们在未明确指定任何样式时看到的样式,我们的样式会覆盖这些默认值。

不同浏览器对于相同元素的默认样式并不一致,这也是为什么我们在 CSS 的最开始要写 *{padding:0;marging:0};,也就是我们要重置CSS默认样式的。

构建渲染树

CSSOM 树和 DOM 树连接在一起形成一个 render tree,渲染树用来计算可见元素的布局并且作为将像素渲染到屏幕上的过程的输入。

DOM 树和 CSSOM 树连接在一起形成 render tree .

render tree 只包含了用于渲染页面的节点

布局计算了每一个对象的准确的位置以及大小

绘画是最后一步,绘画要求利用 render tree 来将像素显示到屏幕上

渲染树中的每个节点在 Webkit 中称为渲染器或渲染对象。

收下是上面 DOM 和 CSSOM 树的渲染器树的样子:

为了构建渲染树,浏览器大致执行以下操作:

从 DOM 树根节点开始,遍历每一个可见的节点

一些节点是完全不可见的(比如 script标签,meta标签等),这些节点会被忽略,因为他们不会影响渲染的输出

一些节点是通过 CSS 样式隐藏了,这些节点同样被忽略——例如上例中的 span 节点在 render tree 中被忽略,因为 span 样式是 display:none

对每一个可见的节点,找到合适的匹配的CSSOM规则,并且应用样式

显示可见节点(节点包括内容和被计算的样式)

“visibility:hidden”“display:none” 之间的不同,“visibility:hidden” 将元素设置为不可见,但是同样在布局上占领一定空间(例如,它会被渲染成为空盒子),但是 “display:none” 的元素是将节点从整个 render tree 中移除,所以不是布局中的一部分 。

你可以在这里查看 RenderObject 的源代码(在 WebKit 中):

https://github.com/WebKit/web...

我们来看看这个类的一些核心内容:

每个渲染器代表一个矩形区域,通常对应于一个节点的 CSS 盒模型。它包含几何信息,例如宽度、高度和位置。

渲染树的布局

创建渲染器并将其添加到树中时,它没有位置和大小,计算这些值称为布局。

HTML使用基于流的布局模型,这意味着大多数时间它可以一次性计算几何图形。坐标系统相对于根渲染器,使用左上原点坐标。

布局是一个递归过程 - 它从根渲染器开始,它对应于 HTML 文档的 元素。 布局以递归方式继续通过部件或整个渲染器层次结构,为每个需要它的渲染器计算几何信息。

根渲染器的位置为0,0,其尺寸与浏览器窗口的可见部分(即viewport)的大小相同。开始布局过程意味着给每个节点在屏幕上应该出现的确切坐标。

绘制渲染树

在此绘制,遍历渲染器树并调用渲染器的 paint() 方法以在屏幕上显示内容。

绘图可以是全局的或增量式的(与布局类似):

全局 — 整棵树被重绘

增量式 — 只有一些渲染器以不影响整个树的方式改变。 渲染器使其在屏幕上的矩形无效,这会导致操作系统将其视为需要重新绘制并生成绘 paint 事件的区域。 操作系统通过将多个区域合并为一个来智能完成。

总的来说,重要的中要理解绘图是一个渐进的过程。为了更好的用户体验,渲染引擎将尽可能快地在屏幕上显示内容。它不会等到解析完所有 HTML 后才开始构建和布局渲染树,而是解析和显示部分内容,同时继续处理来自网络的其余内容项。

处理脚本和样式表的顺序

当解析器到达

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/100967.html

相关文章

  • JavaScript工作原理(十):渲染引擎优化性能技巧

    摘要:渲染引擎的概述渲染引擎的主要职责是在浏览器屏幕上显示请求的页面。中,渲染树中的每个节点都被称为的渲染器或渲染对象。坐标系相对于根渲染器。增量只有一些渲染器以不影响整个树的方式进行更改。渲染器使其矩形在屏幕上无效。 到目前为止,在我们之前的JavaScript工作原理系列文章中,我们一直关注JavaScript作为一种语言,其功能,它如何在浏览器中执行,如何优化等等。 但是,当您构建We...

    xingqiba 评论0 收藏0
  • JavaScript 工作原理之十一-渲染引擎性能优化技巧

    摘要:在中渲染树中的每个节点即是一个渲染器或者渲染器对象。计算的样式每个渲染器对象代表一个矩形区域通常是和一个节点的盒模型相对应。坐标系统是相对于根渲染器的。根渲染器的定位为和大小即为浏览器窗口的可视化部分比如。渲染器作废其在屏幕上的矩形区域。 原文请查阅这里,略有删减,本文采用知识共享署名 4.0 国际许可协议共享,BY Troland。 本系列持续更新中,Github 地址请查阅这里。 ...

    GraphQuery 评论0 收藏0
  • JavaScript 工作原理之十一-渲染引擎性能优化技巧

    摘要:在中渲染树中的每个节点即是一个渲染器或者渲染器对象。计算的样式每个渲染器对象代表一个矩形区域通常是和一个节点的盒模型相对应。坐标系统是相对于根渲染器的。根渲染器的定位为和大小即为浏览器窗口的可视化部分比如。渲染器作废其在屏幕上的矩形区域。 原文请查阅这里,略有删减,本文采用知识共享署名 4.0 国际许可协议共享,BY Troland。 本系列持续更新中,Github 地址请查阅这里。 ...

    Allen 评论0 收藏0
  • JavaScript 工作原理之十一-渲染引擎性能优化技巧

    摘要:在中渲染树中的每个节点即是一个渲染器或者渲染器对象。计算的样式每个渲染器对象代表一个矩形区域通常是和一个节点的盒模型相对应。坐标系统是相对于根渲染器的。根渲染器的定位为和大小即为浏览器窗口的可视化部分比如。渲染器作废其在屏幕上的矩形区域。 原文请查阅这里,略有删减,本文采用知识共享署名 4.0 国际许可协议共享,BY Troland。 本系列持续更新中,Github 地址请查阅这里。 ...

    RyanQ 评论0 收藏0
  • JavaScript 如何工作系列文章已更新到22篇

    摘要:为了方便大家共同学习,整理了之前博客系列的文章,目前已整理是如何工作这个系列,可以请猛戳博客查看。以下列出该系列目录,欢迎点个星星,我将更友动力整理理优质的文章,一起学习。 为了方便大家共同学习,整理了之前博客系列的文章,目前已整理 JavaScript 是如何工作这个系列,可以请猛戳GitHub博客查看。 以下列出该系列目录,欢迎点个星星,我将更友动力整理理优质的文章,一起学习。 J...

    lx1036 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<