惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Hacker News: Ask HN
Hacker News: Ask HN
N
News and Events Feed by Topic
Forbes - Security
Forbes - Security
The Last Watchdog
The Last Watchdog
TaoSecurity Blog
TaoSecurity Blog
Schneier on Security
Schneier on Security
SecWiki News
SecWiki News
V
Vulnerabilities – Threatpost
Project Zero
Project Zero
O
OpenAI News
W
WeLiveSecurity
Security Archives - TechRepublic
Security Archives - TechRepublic
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
H
Hacker News: Front Page
Cisco Talos Blog
Cisco Talos Blog
Spread Privacy
Spread Privacy
Help Net Security
Help Net Security
P
Privacy & Cybersecurity Law Blog
K
Kaspersky official blog
S
Security @ Cisco Blogs
Latest news
Latest news
AWS News Blog
AWS News Blog
U
Unit 42
Martin Fowler
Martin Fowler
阮一峰的网络日志
阮一峰的网络日志
S
Secure Thoughts
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Know Your Adversary
Know Your Adversary
Scott Helme
Scott Helme
博客园 - 司徒正美
B
Blog RSS Feed
C
Check Point Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
D
Docker
Google Online Security Blog
Google Online Security Blog
Jina AI
Jina AI
aimingoo的专栏
aimingoo的专栏
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Last Week in AI
Last Week in AI
月光博客
月光博客
C
CXSECURITY Database RSS Feed - CXSecurity.com
S
SegmentFault 最新的问题
NISL@THU
NISL@THU
T
The Blog of Author Tim Ferriss
C
Cisco Blogs
Attack and Defense Labs
Attack and Defense Labs
小众软件
小众软件

青空之蓝

[青空之蓝-2023] - 色彩 | 青空之蓝 [青空之蓝-2022] - 平静 | 青空之蓝 [青空之蓝-2021] - 远望 | 青空之蓝 浅谈垃圾回收 | 青空之蓝 浅谈泛型擦除 | 青空之蓝 浅谈单点登录 | 青空之蓝 使用 Kotlin 编写 Spring 测试 | 青空之蓝 设计模式系列文章 | 青空之蓝 从零实现一个 Java 微框架 - IoC | 青空之蓝 从零实现一个 Java 微框架 - 前言 | 青空之蓝 浅谈 JVM:类加载 | 青空之蓝 浅谈 IO | 青空之蓝 浅谈并发:synchronized & ReentrantLock | 青空之蓝 浅谈并发:CAS & AQS | 青空之蓝 浅谈并发:ThreadLocal | 青空之蓝 浅谈并发:三大特性 | 青空之蓝 浅谈组合注解 & 注解别名 | 青空之蓝 [青空之蓝-2020]-迷茫 | 青空之蓝 Java 系列文章 | 青空之蓝 HTTP 系列文章 | 青空之蓝 浅谈 EatWhatYouKill | 青空之蓝 浅谈可扩展线程池 | 青空之蓝 聊聊写框架 | 青空之蓝 聊聊现状-[2020-09] | 青空之蓝 浅谈并发:锁 | 青空之蓝 浅谈并发:基础 | 青空之蓝 浅谈缓存 | 青空之蓝 无须定义类,Spring 快速注入 Json 参数 | 青空之蓝 浅谈 Proxy 和 Aop | 青空之蓝 从零实现一个 PHP 微框架 - 初始化请求 | 青空之蓝 为 Vue3 添加一个简单的 Store | 青空之蓝 从零实现一个 PHP 微框架 - 服务提供者 | 青空之蓝 WSL2 踩坑记录 | 青空之蓝 浅谈浏览器Event Loop [更新] | 青空之蓝 从零实现一个 PHP 微框架 - Bootstrap 启动加载 | 青空之蓝 从零实现一个 PHP 微框架 - IoC 容器 | 青空之蓝 从零实现一个 PHP 微框架 - PSR & Composer | 青空之蓝 从零实现一个 PHP 微框架 - 前言 | 青空之蓝 MVVM 简单实现 | 青空之蓝 浅谈 DI 和 IoC | 青空之蓝 中间件实现 [PHP] | 青空之蓝 告别 Windows 终端的难看难用,打造好用的 PowerShell | 青空之蓝 VSCode Java输出中文乱码问题解决[更新] | 青空之蓝 Vue-Cli@2 项目迁移日志 | 青空之蓝 Laragon & Scoop 集成踩坑记录 | 青空之蓝 「一行代码」优雅管理 Windows 软件 | 青空之蓝 [青空之蓝-2019]-年度总结 | 青空之蓝 为Vue添加简单的Store | 青空之蓝 为React添加简单的Store | 青空之蓝 为Vuex添加同步Action | 青空之蓝 浅谈B+树 | 青空之蓝 浅谈跳表 | 青空之蓝 浅谈数据库索引 | 青空之蓝 MySQL事务隔离 | 青空之蓝 算法复杂度分析(1) | 青空之蓝 一年来的经验总结 | 青空之蓝 Acrylic - VSCode Extension | 青空之蓝 ace编辑器设置惯性滚动 | 青空之蓝 Java二叉树实现 | 青空之蓝 Java图实现 | 青空之蓝 为apt方式安装的nginx重新编译增加WebDAV | 青空之蓝 XK-Editor - 一个支持富文本和Markdown的编辑器 | 青空之蓝 JS生成列表树 | 青空之蓝 Laravel生成目录树 | 青空之蓝 XK-Note - 集各种神奇功能的云笔记 | 青空之蓝 PHP GD生成验证码 | 青空之蓝 PHP GD图片处理[转换格式-水印-缩略图] | 青空之蓝 Origami - 简洁轻快的WordPress主题 | 青空之蓝 为WordPress启用WorkBox | 青空之蓝 [青空之蓝-2018]-年度总结 | 青空之蓝 VSCode Java手动导入jar和源码包 | 青空之蓝 Windows IP变化自动发送邮件 | 青空之蓝 C链表实现重制版 | 青空之蓝 C 结构体的定义和使用 | 青空之蓝 图的搜索(遍历) - BFS & DFS | 青空之蓝 Java链表实现 | 青空之蓝 C 快速排序 | 青空之蓝 C 插入排序 | 青空之蓝 C 归并排序 | 青空之蓝 C语言链表实现 | 青空之蓝 VSCode配置Java调试环境[Windows] | 青空之蓝 C 选择排序 | 青空之蓝 C 冒泡排序 | 青空之蓝 VSCode配置PHP调试环境[Windows] | 青空之蓝 VSCode配置C/C++ GDB调试环境[Windows] | 青空之蓝 WordPress友情链接模板 | 青空之蓝 Intel Optane 傲腾内存体验 | 青空之蓝 Mysql双机热备实战 | 青空之蓝 博客一年记录 | 青空之蓝 为WordPress启用Service Worker | 青空之蓝 Bing每日一图API | 青空之蓝 iframe延迟加载 | 青空之蓝 写在2018年高考前 | 青空之蓝 The Fox主题汉化分享 | 青空之蓝 [青空之蓝-2017]-崭新 | 青空之蓝 本博客评论规则 | 青空之蓝 世界,您好! | 青空之蓝
浅谈浏览器渲染 | 青空之蓝
Otstar Lin · 2020-03-06 · via 青空之蓝

浅谈浏览器渲染

好久没写理论性较强的文章了。最近刚好正在了解浏览器的工作原理,于是打算写一篇文章来加强下,输出才是最好的输入嘛 hhhh。

什么是渲染?

在计算机图形学的领域 渲染render 的翻译,看到这个词,写过 React 的开发者应该很熟悉,在 React 中 render 函数做的是将 数据 变成 HTML 代码 的工作。而在图形学中 render 指的是由 模型 生成 图像 的过程,同理在浏览器中 render 做的就是将 DOM 绘制成我们可以看到的 网页。

在谈真正的 渲染 之前,我们需要先了解 布局树 是如何生成的,有助于更好的了解后续的渲染过程。

加载

当用户开始访问一个页面的时候,浏览器就会向服务器请求资源,当网络进程从服务器获取到数据的时候,就会将数据发给渲染进程的 HTML 解析器进行解析,这个过程是实时的,也就是说网络进程收到多少数据,HTML 解析器就解析多少数据,而不会等网络进程收到所有数据后才解析 HTML

解析

DOM

当渲染进程收到 HTML 字节流 的时候,就会调用 HTMLParser 把 HTML 解析成 DOM 树,具体流程见下图:

渲染进程收到字节流时会根据指定编码(UTF-8 等)把字节流转换成字符串,也就是我们写的代码。而渲染引擎是无法直接理解和使用代码的,所以需要将 HTML 转换为浏览器能理解的结构,即 DOM 树

要将 HTML 转换成 DOM 树还要经过词法分析,将 HTML 转换为 Tag Token文本 Token,例子如下:

分词完成后,就需要将 Token 解析成 DOM 节点,并将其添加到 DOM 树中,解析的过程这里就不写了,最终生成的 DOM 树如下所示:

CSSOM

和 HTML 一样,渲染引擎也是无法直接理解和使用 CSS 的所以需要将其解析成渲染引擎能够理解的结构,这个结构就是 CSSOM。浏览器解析 CSS 文件并生成 CSS 规则树,每个 CSS 文件都被分析成一个 StyleSheet 对象,每个对象都包含 CSS 规则。CSS 规则对象包含对应于 CSS 语法的选择器和声明对象以及其他对象。

当 CSS 转换成浏览器可以理解的结构的时候,那么接下来就要对其属性值进行标准化操作。CSS 中一般都有各种各样的单位,如 rem em blue bold 等,这些类型数值不容易被渲染引擎理解,所以需要将所有值转换为渲染引擎容易理解的、标准化的计算值,这个过程就是属性值标准化。具体样例见下图:

样式已经标准化了,下一步就是计算 DOM 树各个节点的样式和属性了。

首先是继承,CSS 中部分样式是可以被子元素继承的,这些可以继承的属性应该同时添加到子元素的样式中。然后是层叠,层叠是 CSS 的一个基本特征,它是定义了如何合并多个不同来源的样式的算法。CSS 的全称即层叠样式表即说明了层叠这个特性在 CSS 中的重要地位。

最终生成的 CSSOM 如下:

布局树

有了渲染引擎可以理解的 DOM 树CSSOM 树,就可构造成最终要绘制的布局树了。

为了构建布局树,浏览器大体上完成了下面这些工作:

  • 遍历 DOM 树中的所有可见节点,并把这些节点加到布局中;
  • 而不可见的节点会被布局树忽略掉,如 head 标签下面的全部内容,再比如属性包含 dispaly:none 的元素等等。

布局计算 & 分层

此时,渲染引擎就可以根据这个布局树来绘制网页了,但是在绘制之前,还需要进行节点的布局计算,布局计算首先需要计算出各个节点的位置坐标,但是只有坐标还不够,因为页面中还有复杂的变化、滚动、层叠和 z-index 排序等等的情况,浏览器为了实现这些就需要创建图层,就像用 PhotoShop 绘图一样,最终这些图层才构成了我们所看到的页面图像。Chrome 给我们提供了很好的开发者工具,我们可以通过 Chrome 的开发者工具来查看网页的图层信息,如下(博主使用的是 New Edge):

从工具中我们可以清晰的看到图层是如何放置并最终形成了我们所看到的页面。具体的分层这里就不说了,有兴趣的可以自行查阅。( ̄︶ ̄)↗

绘制

完成上面的步骤后,渲染引擎就可以绘制每个图层。渲染引擎绘制页面的方式其实和写 SVG 矢量图一样,都是从基本图形开始绘制的,渲染引擎会把图层拆分成很多小的步骤,然后提交到合成线程逐一进行绘制,剩下的步骤就是光栅化、合成和显示,最终就形成了我们所见到的页面,这里就不写了(因为我也不太懂这些计算机图形学的东西 2333

重排 & 重绘 & 合成

重排,顾名思义,即重新排列,我们经常能在各种文章中看到重排的开销很大,重排的开销很大是因为它会改变页面的布局,改变页面布局就需要重新计算布局,分层以及绘制,经过了很多子阶段。所以我们在写代码中应尽量避免重排,任何会改变元素的位置或尺寸大小的操作都会触发重排。

重绘,即重新绘制,不同于重排,重绘并没有改变布局,所以重绘的可以跳过计算布局和分层的步骤,而是直接进入绘制,所以执行效率会高上一点。任何改变元素颜色,显示效果的操作都会触发重绘。

合成,合成是跳过主线程的布局计算,分层和生成绘制列表的部分,直接发由合成线程进行合成操作,相比重排和重绘,合成效率是最高的。使用 CSS 的 transform 来实现的效果触发的是合成。

阻塞渲染

在进行分析阻塞渲染之前我们需要知道以下几点:

  • 布局树依赖于 DOM 和 CSSOM,当 CSSOM 未加载完成的时候浏览器不会构建布局树和绘制页面
  • JavaScript 有操作 DOM 和 CSSOM 的能力

当 HTML 解析器解析到 script 标签的时候,此时 HTML 解析器会暂停对 DOM 的解析和构建,因为 JavaScript 有可能会更改 DOM 的结构,如果不暂停 DOM 解析就有可能导致更新丢失的情况出现。HTML 解析器需要等到 script 标签中的 JavaScript 代码执行完毕才会恢复解析,但是通常我们会通过引入 JavaScript 文件,在执行这个 JavaScript 之前需要先下载 这个 JavaScript 文件,而在下载的过程中 DOM 的解析和构建就被阻塞住了,一般情况下,下载是非常耗时的。所以我们就应该要尽量将 script 文件放置于 HTML 文档的末尾,防止造成过长的白屏。

说完了 JavaScript 的情况我们来说说 CSS,由于 CSSOM 和 DOM 的构建是独立的,所以在只有 HTML 和 CSS 的页面中,CSS 并不会阻塞 DOM 的构建。但是,如果在页面中包含了 JavaScript 那就有所不同了,当解析到了 JavaScript 脚本的时候,DOM 的解析和构建会暂停,此时 JavaScript 引擎会开始执行 JavaScript 代码,但是由于 JavaScript 拥有修改 CSSOM 的能力,那么在执行 JavaScript 代码之前,就需要将 CSS 解析成 CSSOM,也就是所 CSS 在部分情况下也会阻塞 DOM 的解析和构建。

不过,现代浏览器都提供了预解析的功能,在 DOM 的解析和构建被阻塞的时候,解析器会停止构建 DOM,但是仍然会继续解析后面的资源,当解析到需要从网络中获取的资源,浏览器就会预加载这些资源。

下图可以大概体现执行的顺序,不过图画的不太准确,请不要认为这就是真正的执行流程。

结语

至此文章就讲完了浏览器渲染的流程,希望大家能有所收获,写出更好的代码,本文是博主通过阅读一些网络文章结合自己的理解写成的,所以可能会有一些错误之处,如果您发现了文章的错误欢迎留言纠正。[]~( ̄ ▽  ̄)~*

浅谈浏览器渲染

https://blog.ixk.me/post/talking-about-browser-render
  • 许可协议

    BY-NC-SA

  • 本文作者

    Otstar Lin

  • 发布于

    2020/03/06

转载或引用本文时请遵守许可协议,注明出处、不得用于商业用途!

VSCode Java输出中文乱码问题解决[更新]Vue-Cli@2 项目迁移日志