浏览器详解(四) 渲染
大家好,我是半虹,这篇文章来讲浏览器渲染
1、基本介绍
浏览器是多进程多线程的架构,包括有浏览器进程、渲染器进程、GPU 进程、插件进程等
在上篇文章中我们介绍过浏览器进程,作为浏览器主进程,负责浏览器基本界面的交互和底层功能的执行
在这篇文章中我们来介绍渲染器进程,这是浏览器的内核,也称为渲染进程
渲染进程负责标签页内所发生的事情,主要包括页面渲染、脚本执行、事件处理等
其中包含多个重要的线程以协同工作:
-
GUI渲染线程:负责页面的渲染,解析 HTML、CSS,构建 DOM、CSSOM,布局和绘制等如果页面要回流或重绘,也由该线程去执行
-
JS引擎线程:负责解析和执行 JavaScript 脚本,注意JS引擎线程与GUI渲染线程互斥 -
事件触发线程: 控制事件循环,并管理事件队列
若当
JS引擎执行触发异步事件,会将对应的任务交给相应的线程执行处理等到任务完成之后,把任务对应的回调添加到事件队列,等待
JS引擎处理 -
定时触发线程: 负责处理特定任务,具体来说就是用于
setTimeout和setInterval计时等到计时结束,通知事件触发线程,由事件触发线程将对应的回调加入队列
-
异步请求线程: 负责处理特定任务,具体来说就是处理
AJAX请求等到请求完成,通知事件触发线程,由事件触发线程将对应的回调加入队列
下面我们通过例子,异步请求和定时操作,来说明线程之间如何协同工作
上述多个线程大体上可以分成两组:
- 渲染引擎:其中核心为
GUI渲染线程 - 脚本引擎:其中核心为
JS引擎线程,辅助为事件触发线程、定时触发线程、异步请求线程
目前市面主流浏览器使用的渲染引擎和脚本引擎总结如下:
| 浏览器 | 渲染引擎 | 脚本引擎 |
|---|---|---|
Safari | Webkit / WebCore | Webkit / JavaScriptCore |
Chrome | Blink | V8 |
Firefox | Gecko | SpiderMonkey → TraceMonkey → JaegerMonkey |
IE | Trident | Chakra |
Edge | EdgeHTML | Chakra |
在这篇文章中我们主要介绍渲染过程,至于 JS 的解析过程,以后有空的话会专门再讲
好了,下面来正式开始介绍浏览器中的渲染过程
2、渲染流程
渲染引擎渲染页面的过程,也称为关键渲染路径,具体步骤如下:
-
解析 HTML 构建 DOM
具体步骤如下:
转换:从网络或磁盘读取 HTML 文件原始字节,根据文件编码将字节转换为字符串
分词:根据 HTML 规范,将上述字符串切分为不同的标记,如
<html>、<body>语法 分析:将上述标记转换为对象,对象中包含语法信息,如属性、属性值等信息
DOM构建:将上述对象链接在树状的结构中以标识父子和兄弟关系,这个树状结构就是 DOM
需要注意的是:
在读取 HTML 时,DOM 的构建已经开始,可以将上面的步骤理解成是流水线并行
上一个步骤每完成一点,就会将结果传递给下一个步骤,不会等一个步骤完全执行完才进行下一个步骤
关于脚本资源:
当 HTML 解析器遇到
<script>标签时,会暂停 HTML 的解析,并开始加载、解析和执行 JavaScript这是因为 JavaScript 可能会修改 DOM 的结构,若明确 JavaScript 不会修改 DOM, 那么:
你可以为
<script>标签加async属性,这样是异步加载 JavaScript,但是加载完马上就会开始执行也可以为
<script>标签加defer属性,这也是异步加载 JavaScript,且等 DOM 构建完才开始执行
其实如果 JavaScript 确实要修改 DOM 某节点,那也该将其放到 DOM 的构建之后
否则有些获取元素的 操作可能就不能生效
关于外部资源:
一个网页通常包含多个外部资源,例如图片、CSS、JavaScript、字体等等
在解析 DOM 过程中,会按文档的顺序逐一发起请求 ,但是为了提高效率会同时运行预加载扫描器
预加载扫描器查看已切分的标记,从中寻找资源地址并告知网络线程请求
如此当 HTML解析被 JavaScript 阻塞时,预加载扫描器也能继续请求资源
-
解析 CSS 构建 CSSOM
具体步骤如下:
搜集:从内联样式、内部样式表、外部样式表、浏览器代理样式中,搜集所有样式规则
构建:按上述规则构建 CSSOM 树状结构,其中每个节点表示一个样式规则,包含选择器以及样式声明
匹配:遍历 DOM 节点匹配选择器,并为匹配的节点执行样式设置
计算:计算 DOM 节点的最终样式,这些样式可通过以下接口查看:
window.getComputedStyle()
需要注意的是:
上述匹配步骤,CSS 选择器会从右往左匹配 DOM 节点,举个例子,假设 CSS 选择器为
.nav span那么匹配之时,首先找到所有
span节点,然后对每个span节点,向上找.nav节点
另外注意的是:
构建 DOM 和构建 CSSOM 是同时进行的,但是这并不意味着二者不会相互影响
因为 CSSOM 构建会阻塞脚本执行,而脚本执行会阻塞 DOM 构建,有一个间接的影响
-
布局 (Layout)
有了 DOM 和 CSSOM 后,需要根据二者构建出渲染树 (RenderObject Tree)
渲染树只会包含可见元素,像 head 节点和 display 为 none 的节点,则不会出现在渲染树中
至此,其实已经知道每个可见节点的样式,接下来需要根据渲染树进行布局计算
即根据盒子模型和视觉格式化模型来计算每个节点在设备视口内的位置以及大小
当页面布局和几何信息发生变化时,浏览器需要重新布局,这个过程被称为回流 (reflow)
具体又可分为全局布局和局部布局,常见的引起回流阶段的操作如下:
- 页面第一次进行渲染
- 窗口的尺寸发生改变
- 增加或删除可见元素
- 元素的位置发生改变
- 元素的大小发生改变
- …
-
绘制 (Paint)
绘制实际上就是遍历渲染树,在屏幕中绘制出对应的节点内容,简单来说就是个像素填充的过程
绘制过程在多个层上完成的,这些层被称为渲染层 (Render Layer)
渲染树中每个节点都是一个渲染对象,处于相同坐标空间 (z 轴) 的渲染对象会合并到同一个渲染层
对于满足层叠上下文条件的渲染对象,浏览器会为其自动创建新的渲染层,常见情况如下:
- 根元素
- 有
mask属性 - 有
filter属性 - 有
reflection属性 - 有
position属性且值为absolute、relative、fixed、sticky - 有
backface-visibility属性且值为hidden - 有
transform属性且值不为none - 有
overflow属性且值不为visible - 有
opacity属性且值小于1 - 对
opacity、transform、filter等属性应用动画
满足上述条件的渲染对象拥有独立的渲染层,但这并不意味着这些渲染对象独享该渲染层
这是因为不满足上述条件的渲染对象将会与第一个拥有渲染层的父元素共用同一个渲染层
当元素样式有变化但不影响布局时,浏览器需要重新绘制,这个过程被称为重绘 (repaint)
具体又可分为全局绘制和局部绘制,常见的引起重绘阶段的操作如下:
- 修改元素
color - 修改元素
background-color - …
值得注意的是:回流一定引起重绘,重绘不一定引起回流
-
合成 (Composite)
合成阶段中,多个渲染层按照恰当的重叠顺序进行合并,而后生成位图,最终通过显卡展示在屏幕上
在这过程中,某些渲染层会被浏览器自动提升为合成层 (Compositing Layer), 常见情况如下:
- 有
will-change属性 - 有
position属性且值为fixed - 有
transform属性且值为translate3d、translateZ等 3D 变换 - 是
canvas、video、iframe等元素 - 对
opacity、transform、filter等属性应用动画
每个合成层拥有单独的 Graphics Layer 用于生成位图,并上传到 GPU 对其进行合成,绘制到屏幕上
其它不是合成层的渲染层与第一个拥有 Graphics Layer 的父层级共用
合成层有什么用?答案是硬件加速,即把某些需要频繁回流和重绘的元素单独提升成为合成层
这样不仅可以提高绘制的效率,也能减少这些元素修改时对其它元素影响
例如修改合成层的
transform时,不会带来回流或重绘,只需要将多个图层再次合并,而后生成位图这样我们可以通过
transform:translate修改元素位置,通过transform:scale修改元素大小 - 有
渲染进程的工作对浏览器性能有重要影响,常见渲染优化包括:
- 关键样式资源放在头部加载,善用
preload、prefetch - 脚本资源通常放在脚部加载,善用
async、defer - 尽量减少回流以及重绘操作,例如 批量修改 DOM 、离线修改 DOM 等等
- 对于画布,常用的技术包括有分层 canvas、离屏 canvas 等等
- 对于动画,使用
requireAnimationFrame代替setTimeout - 硬件加速
- …
类似方法有很多,这些都需要在日常开发中不断地积累,并有意识地应用到未来开发中
好啦,本文到此结束,感谢您的阅读!
如果你觉得这篇文章有需要修改完善的地方,欢迎在评论区留下你宝贵的意见或者建议
如果你觉得这篇文章还不错的话,欢迎点赞、收藏、关注,你的支持是对我最大的鼓励 (/ω\)
相关文章:
浏览器详解(四) 渲染
大家好,我是半虹,这篇文章来讲浏览器渲染 1、基本介绍 浏览器是多进程多线程的架构,包括有浏览器进程、渲染器进程、GPU 进程、插件进程等 在上篇文章中我们介绍过浏览器进程,作为浏览器主进程,负责浏览器基本界面的…...
idea新建一个module时,文件夹显示灰色/pom.xml文件显示灰色且中间有条横线
1.问题 2.解决方法 File->Settings->Ignored Files->找到勾选的pom.xml文件,取消勾选,点击ok即可。 3.已解决...
NoSQL数据库(林子雨慕课课程)
文章目录 5.1 NoSQL数据库5.2 NoSQL和关系数据库的比较5.3 四大类型NoSQL数据库5.3.1 键值数据库和列族数据库5.3.2 文档数据库、图数据库、以及不同数据库比较分析 5.4 NoSQL数据库的理论基石CAP理论:BASE理论:Eventual consistency(最终一致…...
模拟器运行在AndroidStudio内部,设置其独立窗口显示
在窗口内部运行 设置成独立窗口 Android Studio->Settings或Preferences->Tools->Emulator->取消勾选Launch in the Running Devices tool window --->点击右下角的OK按钮 ---> 重启Android Studio 再次启动模拟器...
计算机网络 | 体系结构
计算机网络 | 体系结构 计算机网络 | 体系结构概念及功能计算机网络简介计算机网络的功能因特网发展阶段小结 组成与分类计算机网络的组成计算机网络的分类小结 标准化工作及相关组织速率相关性能指标速率带宽吞吐量小结 时延相关性能指标时延时延带宽积往返时延RTT利用率小结 …...
ELK 处理 SpringCloud 日志
在排查线上异常的过程中,查询日志总是必不可缺的一部分。现今大多采用的微服务架构,日志被分散在不同的机器上,使得日志的查询变得异常困难。工欲善其事,必先利其器。如果此时有一个统一的实时日志分析平台,那可谓是雪…...
mac使用python递归删除文件夹下所有的.DS_Store文件
import osfolder_path "yourself file path"for root, dirs, files in os.walk(folder_path):for filename in files:if filename .DS_Store:file_path os.path.join(root, filename)os.remove(file_path)print("delete ok")...
Gitlab+Jenkins自动化部署,解放双手
项目打包 在部署项目前需要对源码进行打包,一个简单的SpringBoot项目默认是打包为jar包,也就是在pom.xml中的<packaging>jar</packaging>方式,当然也会有一些打包成war包方式,使用外置的Tomcat应用服务器部署war包…...
NNDL:作业3
在Softmax回归的风险函数(公式(3.39))中如果加上正则化项会有什么影响? (1) 在 Softmax 回归的风险函数中加入正则化项会对模型的训练产生影响。正则化项的作用是对模型的复杂度进行惩罚,防止过拟合的发生。 (2) 原书公式为: 在加入正则化后损失函数…...
dockers --cap-add 哪些值可以设置
--cap-add 参数可以用于向 Docker 容器添加不同的权限。除了 NET_ADMIN,还有一些其他常用的权限值,包括: SYS_ADMIN:添加系统管理员权限,允许容器内的进程执行系统级别的管理操作,如挂载文件系统、设置时间…...
golang常用库之-HTTP客户端请求库 grequests
文章目录 golang常用库之-HTTP客户端请求库 grequests什么是grequests使用 golang常用库之-HTTP客户端请求库 grequests 什么是grequests 官网:github.com/levigross/grequests A Go “clone” of the great and famous Requests library Go语言的grequests库是一…...
17基于matlab卡尔曼滤波的行人跟踪算法,并给出算法估计误差结果,判断算法的跟踪精确性,程序已调通,可直接运行,基于MATLAB平台,可直接拍下。
17基于matlab卡尔曼滤波的行人跟踪算法,并给出算法估计误差结果,判断算法的跟踪精确性,程序已调通,可直接运行,基于MATLAB平台,可直接拍下。 17matlab卡尔曼滤波行人跟踪 (xiaohongshu.com)...
SpringCloud之Stream框架集成RocketMQ消息中间件
Spring Cloud Stream 是一个用来为微服务应用构建消息驱动能力的框架。它可以基于 Spring Boot 来创建独立的、可用于生产的 Spring 应用程序。Spring Cloud Stream 为一些供应商的消息中间件产品提供了个性化的自动化配置实现,并引入了发布-订阅、消费组、分区这三…...
与创新者同行!Apache Doris 首届线下峰会即将开启,最新议程公开!|即刻预约
点击此处 即刻报名 Doris Summit Asia 2023 回顾人类的发展史,地球起源于 46 亿年前的原始星云、地球生命最初出现于 35 亿年前的原始海洋、人类物种诞生于数百万年前,而人类生产力的真正提升源于十八世纪六十年代的工业革命,自此以后&#…...
vue解决:Parsing error: No Babel config file detected for ....
报错信息 Parsing error: No Babel config file detected for C:\Users\Admin\Desktop\shabi\work\src\App.vue. Either disable config file checking with requireConfigFile: false, or configure Babel so that it can find the config files. 分析错误:没有检测…...
算法题:K 次取反后最大化的数组和(典型的贪心算法问题)
这道题没有看题解,直接提交,成绩超越99.5%,说明思路是优的。就是考虑的情况里面弯弯绕比较多,需要考虑全面一点。(本题完整题目附在了最后面) 具体思路如下: 1、首先排序,然后从最…...
Go语言中向[]byte数组中增加一个元素
要向http.Request的body中添加一个键值对,可以先将其转换为一个map,然后对其进行修改,最后再将其转回为byte数组。 以下是一个示例代码: import ("net/http""io/ioutil""encoding/json" )type Re…...
CSS 布局案例: 2行、多行每行格数不定,最后一列对齐
布局期望的效果如下: 第二行最后一格与第一行最后一格对齐。每行格数不定。自动拉伸填充整个宽度 实现: 一开始打算用display:flex, 自动分散,但是第二行对齐第一行最后一格控制不了。 使用grid fr均分单位控制。 <!DOCTYPE…...
数据结构--算法、数据结构的基本概念
📕参考:王道 一、算法的基本概念 1.程序数据结构算法 2.算法的特性 (1)有穷性 执行有穷步之后结束,且每一步都可在有穷时间内完成。 (2)确定性 (3)可行性 可通过已经实…...
Edge浏览器下载文件被保存为 .crdownload 文件的问题小记
问题 近期使用Edge浏览器下载文件时,文件都被保存为 .crdownload 格式的文件了,不确定从哪个版本开始的。除非下载未完成导致文件不完整,否则不会被保存为 .crdownload 格式的文件;实际上文件已完成了下载,且手工修改…...
Decepticon:基于AI的自主红队平台架构与实战解析
1. 项目概述:Decepticon,一个为专业红队而生的自主黑客智能体在网络安全领域,尤其是红队测试中,我们常常面临一个困境:攻击面在指数级增长,而人的精力和时间却是线性的。传统的渗透测试工具链虽然强大&…...
汽车销售网站(10015)
有需要的同学,源代码和配套文档领取,加文章最下方的名片哦 一、项目演示 项目演示视频 二、资料介绍 完整源代码(前后端源代码SQL脚本)配套文档(LWPPT开题报告/任务书)远程调试控屏包运行一键启动项目&…...
从零到顶刊投稿,Perplexity辅助研究全流程,精准定位高影响力论文与方法论缺口
更多请点击: https://intelliparadigm.com 第一章:Perplexity学术研究最佳实践概览 Perplexity 是衡量语言模型预测能力的核心指标,其数学定义为交叉熵的指数形式:\( PPL 2^{-\frac{1}{N}\sum_{i1}^{N}\log_2 p(w_i \mid w_{数据…...
航空航天装备行业技术岗结构设计工程师晋升CTO
下面我直接给你:航空航天装备行业「结构设计工程师 → CTO」的完整岗位链 每级年限 薪资(军工院所 vs 商业航天 2026 实价) 关键跃迁点,全部按结构岗真实晋升路线写死,不掺虚的。一、总路线(结构工程师 →…...
从矩阵求逆到元素倒数:用Matlab power函数处理数据时,90%的人会踩的坑
从矩阵求逆到元素倒数:用Matlab power函数处理数据时,90%的人会踩的坑 在科学计算和工程分析中,Matlab作为一款强大的工具被广泛应用。然而,许多用户在数据处理过程中常常陷入一个看似简单却影响深远的陷阱——混淆矩阵元素的倒数…...
保姆级教程:在Win10上用VS2022搞定TensorRT 8.5.2.2(含zlibwapi.dll缺失等常见坑点)
从零到一:Windows 10 VS2022 深度集成 TensorRT 8.5 全流程实战 TensorRT 作为 NVIDIA 推出的高性能深度学习推理引擎,能够显著提升模型在 NVIDIA GPU 上的执行效率。但对于 Windows 平台的新手开发者来说,从环境配置到第一个示例程序成功运…...
用Fiddler和Proxifier抓包分析易游网络验证API,手把手教你模拟合法请求
网络验证API抓包与模拟请求实战指南 在当今数字化产品生态中,网络验证机制已成为软件授权管理的核心组件。不同于传统的本地验证方式,网络验证通过远程API交互实现更高安全性的许可控制,这也使得协议层分析成为理解其工作原理的关键切入点。对…...
OAI 5G核心网搭建后,如何用Docker命令进行日常运维和故障排查?
OAI 5G核心网Docker运维实战:从日志分析到故障排查 当OAI 5G核心网完成基础部署后,真正的挑战才刚刚开始。面对由多个容器组成的复杂系统,如何快速定位AMF拒绝注册的原因?SMF的PDU会话建立失败该如何排查?本文将分享一…...
独立开发者如何通过taotoken以更低成本实验多种大模型能力
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 独立开发者如何通过Taotoken以更低成本实验多种大模型能力 对于独立开发者或小型工作室而言,在项目原型阶段验证不同大…...
WinMerge过滤器进阶:从基础规则到实战场景配置
1. WinMerge过滤器入门:从零开始理解规则配置 WinMerge作为一款老牌开源文件对比工具,其过滤器功能常常被低估。很多开发者只是用它来排除版本控制目录,但实际上它能做的远不止这些。我第一次接触WinMerge过滤器是在处理一个Java项目时&#…...
